日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

JavaEE——Spring学习笔记03【AOP开发】

發布時間:2024/1/18 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaEE——Spring学习笔记03【AOP开发】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JavaEE——Spring學習筆記01【Ioc開發的模式】

JavaEE——Spring學習筆記02【Spring和Mybatis的整合】

JavaEE——Spring學習筆記03【AOP開發】

JavaEE——Spring學習筆記04【Spring的事務管理】

JavaEE——Spring學習筆記05【Mybatis的逆行工程】

JavaEE——Spring學習筆記06【Maven創建Web工程】

目錄

六、Spring的AOP開發

1. AOP的概念

2. 動態代理(了解)

? 2.1 JDK動態代理

?2.2 Cglib動態代理

3. AOP的編程的好處

4. AOP的編程相關術語

?5. AOP的開發模式

?5.1 Aop的Xml開發方式

5.2 Aop的注解開發方式


六、Spring的AOP開發

1. AOP的概念

????????AOP的英文全程為Aspect Oriented programming,叫做面向切面編程,主要是在運行期間動態實現在不修改源碼的情況下給程序及進行功能增強。針對目標功能進行擴展或是增強,通俗來說就是不修改源碼,讓目標獲得它本身沒有用的新功能。其實就是OOP編程的一個補充,降低了代碼的耦合性。

? ? ? ?AOP開發的底層是通過動態代理來完成,動態代理分為JDK動態代理Cglib動態代理

??????JDK動態代理:依賴于一個接口

??????Cglib動態代理:依賴一個

2. 動態代理(了解)

? 2.1 JDK動態代理

????只能對實現了接口的類產生代理。

實現的步驟:

????????1)業務的接口和實現類

/** 用戶的接口* */ public interface UserDao {public void save();public void update();public void find();public void delete(); } /** 用戶接口實現類* */ public class UserDaoImpl implements UserDao {@Overridepublic void save() {System.out.println("保存用戶信息");}@Overridepublic void update() {System.out.println("更改用戶信息");}@Overridepublic void find() {System.out.println("查詢用戶信息");}@Overridepublic void delete() {System.out.println("刪除用戶信息");} }

????????2)JDK動態代理的類

/** JDK動態代理的類:實現Invocation Handler* */ public class JdkProxy implements InvocationHandler {//將被增強的對象傳遞進來(目標類)private UserDao userDao;public JdkProxy(UserDao userDao) {this.userDao = userDao;}//產生UserDao代理的方法public UserDao createProxy() {/** 第一個參數:UserDao類的加載器* 第二個參數:要實現的接口* */UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(), this);return userDaoProxy;}/* 方法功能增強* 第一個參數: 代理對象* 第二個參數: 真正執行的方法* 第三個參數: 是方法的參數* */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("save".equals(method.getName())) {//增強System.out.println("權限校驗==========");return method.invoke(userDao, args);}return method.invoke(userDao, args);} }

????????3)測試方法

/** 用戶方法增強的測試類* */ public class UserDaoTest {public static void main(String[] args) {//創建一個UserDao的實現類對象UserDao userDao = new UserDaoImpl();//創建代理的對象UserDao proxy = new JdkProxy(userDao).createProxy();proxy.save();proxy.update();proxy.find();proxy.delete();} }

?

?2.2 Cglib動態代理

???????1)針對類而言:引入第三代理的jar包

<!--添加Cglib動態代理的jar包--><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.1_3</version></dependency>

???????2)目標類

/** 客戶信息的類* */ public class CustomerService {public void save() {System.out.println("保存用戶信息");}public void update() {System.out.println("更改用戶信息");}public void find() {System.out.println("查詢用戶信息");}public void delete() {System.out.println("刪除用戶信息");} }

? ? ???3)Cglib代理的類

/** CglibProxy動態代理的類:實現MethodInterceptor* */ public class CglibProxy implements MethodInterceptor {//給出要代理的對象private CustomerService customerService;public CglibProxy(CustomerService customerService) {this.customerService = customerService;}/** 使用Cglib產生代理的方法* */public CustomerService createProxy() {//1.創建Cglib的核心類的對象Enhancer enhancer = new Enhancer();//2.設置父類enhancer.setSuperclass(customerService.getClass());//3.設置回滾enhancer.setCallback(this);//4.創建代理的對象CustomerService proxy = (CustomerService) enhancer.create();return proxy;}/** 功能增強* */@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//判斷方法if ("delete".equals(method.getName())) {//增強System.out.println("日志信息==========");return methodProxy.invokeSuper(proxy, args);}return methodProxy.invokeSuper(proxy, args);} }

? ? ? ?4)測試的類

/** 客戶信息測試類* */ public class CustomerServiceTest {public static void main(String[] args) {//創建一個目標類CustomerService customerService = new CustomerService();//代理過程CustomerService proxy = new CglibProxy(customerService).createProxy();proxy.save();proxy.update();proxy.find();proxy.delete();} }

3. AOP的編程的好處

????????1.減少重復

????????2.專注于業務功能增強的實現,就是oop的補充。

????????3.解模塊之間的耦合性

????????4.實現了事務的功能管理

????????5.。。。。。

4. AOP的編程相關術語

1)切面:Aspect

???切面指的是一個輔助類,實際上就是對業務邏輯的一種增強管理類。

2)連接點:JointPoint

???連接點是指可以被切面植入的具體的方法,通常情況就是業務中的方法均可以作為連接點。

3)切入點:PointCut

???切入點(切點)聲明一個或多個連接點的集合,一般我們理解為真正被增強的那個方法或方法的集合。

4)目標對象:Target

???目標對象就是指被增強的對象,即包含業務邏輯的類的對象

5)通知:Advice

???通知定義了增強代碼切入到目標代碼的時間點(可前可后進行增強),是目標方法執行前還是執行后等,通知的類型不同,導致切入的時間點就不一樣了。

6)織入:weaving

???織入就是增強添加對目標類具體連接點的過程。

5. AOP的開發模式

?5.1 Aop的Xml開發方式

? ?Spring本身有自己對AOP開發的實現,但是開發者發現了這個過程太過于繁瑣了,所以在實際開發中我們使用的是AspectJ技術實現對AOP的開發,其實就是簡化Spring本身的開發。其實現方式簡潔、方便管理,而且還支持注解開發。所以Spring又將AspectJ作為AOP實現引入到自己框架中。

log4j.properties日志配置 log4j.rootLogger = debug,stdout,D,Elog4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%nlog4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = D://logs/log.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%nlog4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =D://logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

?5.1.1 前置通知:berfore

1)引入AspectJ的依賴jar包

<dependencies><!--添加單元測試的依賴包--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!--添加Spring的核心jar包--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.7.RELEASE</version></dependency><!--添加AspectJ的依賴包--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.7.RELEASE</version></dependency></dependencies>

2)配置切面(就是業務增強的那個類)AccountAspect?

/** 賬戶類的切面:其實就是Account業務增強的類* */ public class AccountAspect {/** 驗證賬戶的合法性* */public void validAuth() {System.out.println("驗證賬戶是否合法!");}/** 檢查余額是否足夠* */public void validMoney() {System.out.println("檢查余額是否充足!");}/** 生成對賬單* */public void generateStatement() {System.out.println("生產對賬單!");}/** 發送短信* */public void sendMsg() {System.out.println("發送短信!");}/** 后置通知:取完錢后查看余額的方法* */public void getYuMoney(Object result) {System.out.println("賬戶余額還有:" + result);}/** 利用環繞通知檢查余額是否足夠(前置)和生成對賬單(后置)* */public Object validMoneyAndGenerateStatement(ProceedingJoinPoint point) throws Throwable {Object obj = null;//前置通知: 檢查余額是否充足validMoney();obj = point.proceed(); //調用切點的方法//后置通知: 生成對賬單generateStatement();return obj;}/** 異常通知* */public void exception(Exception e) {System.out.println("目標方法執行出錯" + e.getMessage());}/** 最終的通知* */public void after() {System.out.println("不管有無異常,我都進行通知");} }

3) 配置被切面(就是配置目標類)Account?

/** 賬號類* */ public class Account {int money = 1000;//取錢/*public void out() {money -= 100; //取出100元System.out.println("已扣除100元!");}*///取錢public int out() {money -= 100; //取出100元System.out.println("已扣除100元!");int num = 100 / 0; //設置異常return money;}//存錢public void in() {money += 100; //存儲100元System.out.println("已存儲100元!");}//轉賬public void transfer() {System.out.println("轉賬人民幣!");}//開戶public void open() {System.out.println("開通賬戶!");}//銷戶public void close() {System.out.println("銷毀賬戶!");} }

4)配值目標類和切面類的關系applicationContext-aop.xml

? ? ?Spring容器管理

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--1.配置切面: 業務增強的類--><bean id="accountAspect" class="com.suke.aspect.AccountAspect"></bean><!--2.配置被切面: 目標類--><bean id="account" class="com.suke.pojo.Account"></bean><!--3.配置切面和目標類之間的關系--><aop:config><!--3.1 配置切入點:真正被增強的那個點(方法)--><aop:pointcut id="pointcut1" expression="execution(public int com.suke.pojo.Account.out())"/><!--3.2 配置切面,給出增強的方法的執行時間通知的配置:方法被增強的執行時間:之前,之后,環繞,異常,最終--><aop:aspect ref="accountAspect"><!--配置增強的方法--><!--前置通知--><aop:before method="validAuth" pointcut-ref="pointcut1"/><aop:before method="validMoney" pointcut-ref="pointcut1"/><!--后置通知,給出余額參數信息--><aop:after-returning method="getYuMoney" pointcut-ref="ponintcut1" returning="result"/><!--環繞通知--><aop:around method="validMoneyAndGenerateStatement" pointcut-ref="pointcut1"/><!--異常通知--><aop:after-throwing method="exception" pointcut-ref="pointcut1" throwing="e"/><!--最終異常--><aop:after method="after" pointcut-ref="pointcut1"/></aop:aspect></aop:config> </beans>

5)測試類AccountTest?

/** 測試賬戶的類* */ public class AccountTest {@Testpublic void testAccount() {//1.創建Spring容器的對象ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-aop.xml");//2.獲取容器中Account對象Account account = (Account) applicationContext.getBean("account");//取錢account.out();} }

?5.1.2 后置通知:after-returing

???在目標方法執行后進行通知?

1)以取錢后顯示余額為案例,目標類中的方法

//取錢public int out() {money -= 100; //取出100元System.out.println("已扣除100元!");return money;}

2)切面類中的方法

/** 后置通知:取完錢后查看余額的方法* */public void getYuMoney(Object result) {System.out.println("賬戶余額還有:" + result);}

3)Spring容器中的配置

<!--后置通知,給出余額參數信息--><aop:after-returning method="getYuMoney" pointcut-ref="ponintcut1" returning="result"/>

?5.1.3 環繞通知:aroud

在目標方法執行前和執行后都進行通知,修改切面類中的方法!

1)切面類中的方法

/** 利用環繞通知檢查余額是否足夠(前置)和生成對賬單(后置)* */public Object validMoneyAndGenerateStatement(ProceedingJoinPoint point) throws Throwable {Object obj = null;//前置通知: 檢查余額是否充足validMoney();obj = point.proceed(); //調用切點的方法//后置通知: 生成對賬單generateStatement();return obj;}

2)Spring容器中的配置

<!--環繞通知--><aop:around method="validMoneyAndGenerateStatement" pointcut-ref="pointcut1"/>

3)測試類不變

/** 測試賬戶的類* */ public class AccountTest {@Testpublic void testAccount() {//1.創建Spring容器的對象ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-aop.xml");//2.獲取容器中Account對象Account account = (Account) applicationContext.getBean("account");//取錢account.out();} }

?5.1.4 異常通知:after-throwing

1)目標類中的方法

//取錢public int out() {money -= 100; //取出100元System.out.println("已扣除100元!");int num = 100 / 0; //設置異常return money;}

2)切面類中的方法

/** 異常通知* */public void exception(Exception e) {System.out.println("目標方法執行出錯" + e.getMessage());}

3)Spring容器中的配置

<!--異常通知--><aop:after-throwing method="exception" pointcut-ref="pointcut1" throwing="e"/>

4)測試類不變

?5.1.5 最終通知:after

1)切面類中的方法

/** 最終的通知* */public void after() {System.out.println("不管有無異常,我都進行通知");}

2)Spring容器文件中的配置

<!--最終異常--><aop:after method="after" pointcut-ref="pointcut1"/>

3)測試類不變

AOP的總結:

1. 切什么?用什么切?

???找切面與被切面,被切面是業務,切面是擴展業務

2. 從哪切?

???找切點

3. 什么時間切?

???定義通知類型(前置,后置,環繞,異常,最終)

5.2 Aop的注解開發方式

無論是xml的aop開發。還是注解的aopo開發,都可以實現方法增強的功能。

5.2.1 設置注解的包掃描器

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--1、設置注解的包掃描器--><context:component-scan base-package="com.suke"/><!--2、開啟AOP的注解代理--><aop:aspectj-autoproxy/> </beans>

5.2.2 AOP注解在使用前要先開啟

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--1、設置注解的包掃描器--><context:component-scan base-package="com.suke"/><!--2、開啟AOP的注解代理--><aop:aspectj-autoproxy/> </beans>

5.2.3 目標類Account?

/*** 賬戶類:被切面類*/@Component public class Account {int money = 1000;//取錢 /* public void out(){money -=100;//取出100System.out.println("已扣除100元!");}*/public int out() {money -= 100;//取出100System.out.println("已扣除100元!");//int num = 100/0;//設置異常return money;}//存錢public void in() {money += 100;//存儲100System.out.println("已存儲100元!");}//轉賬public void transfer() {System.out.println("轉賬人民幣!");}//開戶public void open() {System.out.println("開通賬戶!");}//銷戶public void close() {System.out.println("賬戶銷戶!");} }

5.2.4 切面類AccountAspect

/*** 賬戶類的切面:其實就是Account業務增強的類*/ @Component @Aspect public class AccountAspect {/*** 驗證賬戶的合法性:前置通知1*/@Before("execution(public int com.suke.pojo.Account.out())")public void validAuth() {System.out.println("驗證賬戶是否合法!");}/*** 檢查余額是否足夠:前置通知2*/@Before("execution(public int com.suke.pojo.Account.out())")public void validMoney() {System.out.println("檢查余額是否充足!");}/*** 生成對賬單*/@AfterReturning("execution(public int com.suke.pojo.Account.out())")public void generateStatement() {System.out.println("生成對賬單!");}/*** 發送短信*/@AfterReturning("execution(public int com.suke.pojo.Account.out())")public void sendMsg() {System.out.println("發送短信!");}/*** 后置通知:取完錢后查看余額的方法*/ // @AfterReturning(value = "execution(public int com.suke.pojo.Account.out())",returning = "result")@AfterReturning(value = "accountPoint()", returning = "result")public void getYuMoney(Object result) {System.out.println("賬戶余額還有:" + result);}/*** 利用環繞通知檢查余額是否足夠(前置)和生成對賬單(后置)*/@Around("execution(public int com.suke.pojo.Account.out())")public Object vaildMoneyAndGenerateStatement(ProceedingJoinPoint ponint) throws Throwable {Object obj = null;//前置通知:檢查余額是否充足validMoney();obj = ponint.proceed(); //調用切點的方法//后置通知:生成對賬單generateStatement();return obj;}/*** 異常通知*/ // @AfterThrowing(value = "execution(public int com.suke.pojo.Account.out())", throwing = "e")@AfterThrowing(value = "accountPoint()", throwing = "e")public void exception(Exception e) {System.out.println("目標方法執行出錯!" + e.getMessage());}/*** 最終的通知*/ // @After("execution(public int com.suke.pojo.Account.out())")@After(value = "accountPoint()")public void after() {System.out.println("不管有無異常我都進行通知!");}/*** 配置一個切點*/@Pointcut(value = "execution(public int com.suke.pojo.Account.out())")public void accountPoint() {} }

5.2.4 測試類AccountTest?

/*** 測試賬戶的類*/ public class AccountTest {@Testpublic void testAccount(){//1、創建Spring的容器對象ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-aop.xml");//2、獲取容器中Account對象Account account = (Account) applicationContext.getBean("account");//取錢account.out();} }

總結

以上是生活随笔為你收集整理的JavaEE——Spring学习笔记03【AOP开发】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。