精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

我們一起了解 Spring 中的 AOP !

開發(fā) 架構(gòu)
AOP的全稱是Aspect-Oriented Programming,即面向切面編程(也稱面向方面編程)。它是面向?qū)ο缶幊?OOP)的一種補(bǔ)充,目前已成為一種比較成熟的編程方式。

[[431585]]

本文轉(zhuǎn)載自微信公眾號「程序員千羽」,作者程序員千羽 。轉(zhuǎn)載本文請聯(lián)系程序員千羽公眾號。

  • 1. Spring AOP簡介
  • 2. 動態(tài)代理
  • jdk動態(tài)代理
  • CGLIB代理
  • 3. 基于代理類的AOP實(shí)現(xiàn)
  • Spring的通知類型
  • ProxyFactoryBean
  • 4. AspectJ開發(fā)
  • 基于XML的聲明式AspectJ
  • 基于注解的聲明式AspectJ(常用)

“GitHub:https://github.com/nateshao/ssm/tree/master/103-spring-aop

1. Spring AOP簡介

什么是AOP?

AOP的全稱是Aspect-Oriented Programming,即面向切面編程(也稱面向方面編程)。它是面向?qū)ο缶幊?OOP)的一種補(bǔ)充,目前已成為一種比較成熟的編程方式。

在傳統(tǒng)的業(yè)務(wù)處理代碼中,通常都會進(jìn)行事務(wù)處理、日志記錄等操作。雖然使用OOP可以通過組合或者繼承的方式來達(dá)到代碼的重用,但如果要實(shí)現(xiàn)某個(gè)功能(如日志記錄),同樣的代碼仍然會分散到各個(gè)方法中。這樣,如果想要關(guān)閉某個(gè)功能,或者對其進(jìn)行修改,就必須要修改所有的相關(guān)方法。這不但增加了開發(fā)人員的工作量,而且提高了代碼的出錯率。

為了解決這一問題,AOP思想隨之產(chǎn)生。AOP采取橫向抽取機(jī)制,將分散在各個(gè)方法中的重復(fù)代碼提取出來,然后在程序編譯或運(yùn)行時(shí),再將這些提取出來的代碼應(yīng)用到需要執(zhí)行的地方。這種采用橫向抽取機(jī)制的方式,采用傳統(tǒng)的OOP思想顯然是無法辦到的,因?yàn)镺OP只能實(shí)現(xiàn)父子關(guān)系的縱向的重用。雖然AOP是一種新的編程思想,但卻不是OOP的替代品,它只是OOP的延伸和補(bǔ)充。

類與切面的關(guān)系

AOP的使用,使開發(fā)人員在編寫業(yè)務(wù)邏輯時(shí)可以專心于核心業(yè)務(wù),而不用過多的關(guān)注于其他業(yè)務(wù)邏輯的實(shí)現(xiàn),這不但提高了開發(fā)效率,而且增強(qiáng)了代碼的可維護(hù)性。

Proxy(代理):將通知應(yīng)用到目標(biāo)對象之后,被動態(tài)創(chuàng)建的對象。

Weaving(織入):將切面代碼插入到目標(biāo)對象上,從而生成代理對象的過程。

2. 動態(tài)代理

jdk動態(tài)代理

“JDK動態(tài)代理是通過java.lang.reflect.Proxy 類來實(shí)現(xiàn)的,我們可以調(diào)用Proxy類的newProxyInstance()方法來創(chuàng)建代理對象。對于使用業(yè)務(wù)接口的類,Spring默認(rèn)會使用JDK動態(tài)代理來實(shí)現(xiàn)AOP。

UserDao.java

  1. public interface UserDao { 
  2.     public void addUser(); 
  3.     public void deleteUser(); 

UserDaoImpl.java

  1. package com.nateshao.aop; 
  2.  
  3. import org.springframework.stereotype.Repository; 
  4.  
  5. /** 
  6.  * @date Created by 邵桐杰 on 2021/10/14 17:59 
  7.  * @微信公眾號 程序員千羽 
  8.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  9.  * @博客 https://nateshao.gitee.io 
  10.  * @GitHub https://github.com/nateshao 
  11.  * @Gitee https://gitee.com/nateshao 
  12.  * Description: 
  13.  */ 
  14. @Repository("userDao"
  15. public class UserDaoImpl implements UserDao{ 
  16.     @Override 
  17.     public void addUser() { 
  18.         System.out.println("添加用戶"); 
  19.     } 
  20.  
  21.     @Override 
  22.     public void deleteUser() { 
  23.         System.out.println("刪除用戶"); 
  24.     } 

JdkProxy.java

  1. package com.nateshao.aop; 
  2.  
  3. import com.nateshao.aspect.MyAspect; 
  4. import java.lang.reflect.InvocationHandler; 
  5. import java.lang.reflect.Method; 
  6. import java.lang.reflect.Proxy; 
  7.  
  8. /** 
  9.  * @date Created by 邵桐杰 on 2021/10/14 18:01 
  10.  * @微信公眾號 程序員千羽 
  11.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  12.  * @博客 https://nateshao.gitee.io 
  13.  * @GitHub https://github.com/nateshao 
  14.  * @Gitee https://gitee.com/nateshao 
  15.  * Description: JDK代理類 
  16.  */ 
  17. public class JdkProxy implements InvocationHandler { 
  18.     // 聲明目標(biāo)類接口 
  19.     private UserDao userDao; 
  20.     // 創(chuàng)建代理方法 
  21.     public  Object createProxy(UserDao userDao) { 
  22.         this.userDao = userDao; 
  23.         // 1.類加載器 
  24.         ClassLoader classLoader = JdkProxy.class.getClassLoader(); 
  25.         // 2.被代理對象實(shí)現(xiàn)的所有接口 
  26.         Class[] clazz = userDao.getClass().getInterfaces(); 
  27.         // 3.使用代理類,進(jìn)行增強(qiáng),返回的是代理后的對象 
  28.         return  Proxy.newProxyInstance(classLoader,clazz,this); 
  29.     } 
  30.  
  31.     /** 
  32.      * 所有動態(tài)代理類的方法調(diào)用,都會交由invoke()方法去處理 
  33.      * @param proxy 被代理后的對象 
  34.      * @param method 將要被執(zhí)行的方法信息(反射) 
  35.      * @param args 執(zhí)行方法時(shí)需要的參數(shù) 
  36.      * @return 
  37.      * @throws Throwable 
  38.      */ 
  39.     @Override 
  40.     public Object invoke(Object proxy, Method method, Object[] args) 
  41.             throws Throwable { 
  42.         // 聲明切面 
  43.         MyAspect myAspect = new MyAspect(); 
  44.         // 前增強(qiáng) 
  45.         myAspect.check_Permissions(); 
  46.         // 在目標(biāo)類上調(diào)用方法,并傳入?yún)?shù) 
  47.         Object obj = method.invoke(userDao, args); 
  48.         // 后增強(qiáng) 
  49.         myAspect.log(); 
  50.         return obj; 
  51.     } 

CGLIB代理

通過前面的學(xué)習(xí)可知,JDK的動態(tài)代理用起來非常簡單,但它是有局限性的,使用動態(tài)代理的對象必須實(shí)現(xiàn)一個(gè)或多個(gè)接口。

如果想代理沒有實(shí)現(xiàn)接口的類,那么可以使用CGLIB代理。

“CGLIB(Code Generation Library)是一個(gè)高性能開源的代碼生成包,它采用非常底層的字節(jié)碼技術(shù),對指定的目標(biāo)類生成一個(gè)子類,并對子類進(jìn)行增強(qiáng)。

UserDao.java

  1. public class UserDao { 
  2.  
  3.     public void addUser(){ 
  4.         System.out.println("添加用戶"); 
  5.     } 
  6.  
  7.     public void deleteUser(){ 
  8.         System.out.println("添加用戶"); 
  9.     } 

CglibProxy.java

  1. package com.nateshao.cglib; 
  2.  
  3. import com.nateshao.aspect.MyAspect; 
  4. import org.springframework.cglib.proxy.Enhancer; 
  5. import org.springframework.cglib.proxy.MethodInterceptor; 
  6. import org.springframework.cglib.proxy.MethodProxy; 
  7. import java.lang.reflect.Method; 
  8.  
  9. /** 
  10.  * @date Created by 邵桐杰 on 2021/10/14 18:18 
  11.  * @微信公眾號 程序員千羽 
  12.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  13.  * @博客 https://nateshao.gitee.io 
  14.  * @GitHub https://github.com/nateshao 
  15.  * @Gitee https://gitee.com/nateshao 
  16.  * Description: 
  17.  */ 
  18. // 代理類 
  19. public class CglibProxy implements MethodInterceptor { 
  20.     // 代理方法 
  21.     public  Object createProxy(Object target) { 
  22.         // 創(chuàng)建一個(gè)動態(tài)類對象 
  23.         Enhancer enhancer = new Enhancer(); 
  24.         // 確定需要增強(qiáng)的類,設(shè)置其父類 
  25.         enhancer.setSuperclass(target.getClass()); 
  26.         // 添加回調(diào)函數(shù) 
  27.         enhancer.setCallback(this); 
  28.         // 返回創(chuàng)建的代理類 
  29.         return enhancer.create(); 
  30.     } 
  31.  
  32.     /** 
  33.      * @param proxy CGlib根據(jù)指定父類生成的代理對象 
  34.      * @param method 攔截的方法 
  35.      * @param args 攔截方法的參數(shù)數(shù)組 
  36.      * @param methodProxy 方法的代理對象,用于執(zhí)行父類的方法 
  37.      * @return 
  38.      * @throws Throwable 
  39.      */ 
  40.     @Override 
  41.     public Object intercept(Object proxy, Method method, Object[] args, 
  42.                             MethodProxy methodProxy) throws Throwable { 
  43.         // 創(chuàng)建切面類對象 
  44.         MyAspect myAspect = new MyAspect(); 
  45.         // 前增強(qiáng) 
  46.         myAspect.check_Permissions(); 
  47.         // 目標(biāo)方法執(zhí)行 
  48.         Object obj = methodProxy.invokeSuper(proxy, args); 
  49.         // 后增強(qiáng) 
  50.         myAspect.log(); 
  51.         return obj; 
  52.     } 

CglibTest.java

  1. package com.nateshao.cglib; 
  2.  
  3. /** 
  4.  * @date Created by 邵桐杰 on 2021/10/14 18:25 
  5.  * @微信公眾號 程序員千羽 
  6.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  7.  * @博客 https://nateshao.gitee.io 
  8.  * @GitHub https://github.com/nateshao 
  9.  * @Gitee https://gitee.com/nateshao 
  10.  * Description: 
  11.  */ 
  12. public class CglibTest { 
  13.     public static void main(String[] args) { 
  14.         // 創(chuàng)建代理對象 
  15.         CglibProxy cglibProxy = new CglibProxy(); 
  16.         // 創(chuàng)建目標(biāo)對象 
  17.         UserDao userDao = new UserDao(); 
  18.         // 獲取增強(qiáng)后的目標(biāo)對象 
  19.         UserDao userDao1 = (UserDao)cglibProxy.createProxy(userDao); 
  20.         // 執(zhí)行方法 
  21.         userDao1.addUser(); 
  22.         userDao1.deleteUser(); 
  23.     } 

3. 基于代理類的AOP實(shí)現(xiàn)

Spring的通知類型

Spring按照通知在目標(biāo)類方法的連接點(diǎn)位置,可以分為5種類型,具體如下:

  • org.springframework.aop.MethodBeforeAdvice(前置通知)

在目標(biāo)方法執(zhí)行前實(shí)施增強(qiáng),可以應(yīng)用于權(quán)限管理等功能。

  • org.springframework.aop.AfterReturningAdvice(后置通知)

在目標(biāo)方法執(zhí)行后實(shí)施增強(qiáng),可以應(yīng)用于關(guān)閉流、上傳文件、刪除臨時(shí)文件等功能。

  • org.aopalliance.intercept.MethodInterceptor(環(huán)繞通知)

在目標(biāo)方法執(zhí)行前后實(shí)施增強(qiáng),可以應(yīng)用于日志、事務(wù)管理等功能。

  • org.springframework.aop.ThrowsAdvice(異常拋出通知)

在方法拋出異常后實(shí)施增強(qiáng),可以應(yīng)用于處理異常記錄日志等功能。

  • org.springframework.aop.IntroductionInterceptor(引介通知)

在目標(biāo)類中添加一些新的方法和屬性,可以應(yīng)用于修改老版本程序。

ProxyFactoryBean

“ProxyFactoryBean是FactoryBean接口的實(shí)現(xiàn)類,F(xiàn)actoryBean負(fù)責(zé)實(shí)例化一個(gè)Bean,而ProxyFactoryBean負(fù)責(zé)為其他Bean創(chuàng)建代理實(shí)例。在Spring中,使用ProxyFactoryBean是創(chuàng)建AOP代理的基本方式。

ProxyFactoryBean類中的常用可配置屬性如下:

代碼實(shí)現(xiàn)

MyAspect.java

  1. package com.nateshao.factorybean; 
  2.  
  3. import org.aopalliance.intercept.MethodInterceptor; 
  4. import org.aopalliance.intercept.MethodInvocation; 
  5.  
  6. /** 
  7.  * @date Created by 邵桐杰 on 2021/10/14 18:36 
  8.  * @微信公眾號 程序員千羽 
  9.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  10.  * @博客 https://nateshao.gitee.io 
  11.  * @GitHub https://github.com/nateshao 
  12.  * @Gitee https://gitee.com/nateshao 
  13.  * Description:  切面類 
  14.  */ 
  15. public class MyAspect implements MethodInterceptor { 
  16.  
  17.     @Override 
  18.     public Object invoke(MethodInvocation mi) throws Throwable { 
  19.         check_Permissions(); 
  20.         // 執(zhí)行目標(biāo)方法 
  21.         Object obj = mi.proceed(); 
  22.         log(); 
  23.         return obj; 
  24.     } 
  25.     public void check_Permissions(){ 
  26.         System.out.println("模擬檢查權(quán)限..."); 
  27.     } 
  28.     public void log(){ 
  29.         System.out.println("模擬記錄日志..."); 
  30.     } 

applicationContext.xml

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  5.  http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> 
  6.     <!-- 1 目標(biāo)類 --> 
  7.     <bean id="userDao" class="com.nateshao.jdk.UserDaoImpl" /> 
  8.     <!-- 2 切面類 --> 
  9.     <bean id="myAspect" class="com.nateshao.factorybean.MyAspect" /> 
  10.     <!-- 3 使用Spring代理工廠定義一個(gè)名稱為userDaoProxy的代理對象 --> 
  11.     <bean id="userDaoProxy" 
  12.           class="org.springframework.aop.framework.ProxyFactoryBean"
  13.         <!-- 3.1 指定代理實(shí)現(xiàn)的接口--> 
  14.         <property name="proxyInterfaces" 
  15.                   value="com.nateshao.jdk.UserDao" /> 
  16.         <!-- 3.2 指定目標(biāo)對象 --> 
  17.         <property name="target" ref="userDao" /> 
  18.         <!-- 3.3 指定切面,織入環(huán)繞通知 --> 
  19.         <property name="interceptorNames" value="myAspect" /> 
  20.         <!-- 3.4 指定代理方式,true:使用cglib,false(默認(rèn)):使用jdk動態(tài)代理 --> 
  21.         <property name="proxyTargetClass" value="true" /> 
  22.     </bean> 
  23. </beans> 

 

 

ProxyFactoryBeanTest.java

  1. package com.nateshao.factorybean; 
  2.  
  3. import com.nateshao.jdk.UserDao; 
  4. import org.springframework.context.ApplicationContext; 
  5. import org.springframework.context.support.ClassPathXmlApplicationContext; 
  6.  
  7. /** 
  8.  * @date Created by 邵桐杰 on 2021/10/14 18:41 
  9.  * @微信公眾號 程序員千羽 
  10.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  11.  * @博客 https://nateshao.gitee.io 
  12.  * @GitHub https://github.com/nateshao 
  13.  * @Gitee https://gitee.com/nateshao 
  14.  * Description: 測試類 
  15.  */ 
  16. public class ProxyFactoryBeanTest { 
  17.     public static void main(String args[]) { 
  18.         String xmlPath = "applicationContext.xml"
  19.         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); 
  20.         // 從Spring容器獲得內(nèi)容 
  21.         UserDao userDao = (UserDao) applicationContext.getBean("userDaoProxy"); 
  22.         // 執(zhí)行方法 
  23.         userDao.addUser(); 
  24.         userDao.deleteUser(); 
  25.     } 

4. AspectJ開發(fā)

“概述:AspectJ是一個(gè)基于Java語言的AOP框架,它提供了強(qiáng)大的AOP功能。Spring 2.0以后,Spring AOP引入了對AspectJ的支持,并允許直接使用AspectJ進(jìn)行編程,而Spring自身的AOP API也盡量與AspectJ保持一致。新版本的Spring框架,也建議使用AspectJ來開發(fā)AOP。使用AspectJ實(shí)現(xiàn)AOP有兩種方式:一種是基于XML的聲明式AspectJ,另一種是基于注解的聲明式AspectJ。

基于XML的聲明式AspectJ

“基于XML的聲明式AspectJ是指通過XML文件來定義切面、切入點(diǎn)及通知,所有的切面、切入點(diǎn)和通知都必須定義在< aop:config >元素內(nèi)。

< aop:config >元素及其子元素如下:

小提示:圖中灰色部分標(biāo)注的元素即為常用的配置元素

XML文件中常用元素的配置方式如下:

  1. <bean id="myAspect" class="com.nateshao.aspectj.xml.MyAspect" /> 
  2. <aop:config> 
  3. <aop:aspect  id="aspect"  ref="myAspect"
  4.     <aop:pointcut expression="execution(* com.nateshao.jdk.*.*(..))“ id="myPointCut" /> 
  5.                   <aop:before method="myBefore" pointcut-ref="myPointCut" /> 
  6.                   <aop:after-returning method="myAfterReturning“ pointcut-ref="myPointCut"                            returning="returnVal" /> 
  7.     <aop:around method="myAround" pointcut-ref="myPointCut" /> 
  8.     <aop:after-throwing method="myAfterThrowing“ pointcut-ref="myPointCut" throwing="e" /> 
  9.                   <aop:after method="myAfter" pointcut-ref="myPointCut" /> 
  10.     </aop:aspect> 
  11. </aop:config> 

 

 

配置切面

“在Spring的配置文件中,配置切面使用的是< aop:aspect >元素,該元素會將一個(gè)已定義好的Spring Bean轉(zhuǎn)換成切面Bean,所以要在配置文件中先定義一個(gè)普通的Spring Bean。

配置< aop:aspect >元素時(shí),通常會指定id和ref兩個(gè)屬性。

id:用于定義該切面的唯一標(biāo)識名稱。 ref:用于引用普通的Spring Bean

配置切入點(diǎn)

“當(dāng)< aop:pointcut>元素作為< aop:config>元素的子元素定義時(shí),表示該切入點(diǎn)是全局切入點(diǎn),它可被多個(gè)切面所共享;當(dāng)< aop:pointcut>元素作為< aop:aspect>元素的子元素時(shí),表示該切入點(diǎn)只對當(dāng)前切面有效。

在定義< aop:pointcut>元素時(shí),通常會指定id和expression兩個(gè)屬性。

id:用于指定切入點(diǎn)的唯-標(biāo)識名稱。. expressione:用于指定切入點(diǎn)關(guān)聯(lián)的切入點(diǎn)表達(dá)式

切入點(diǎn)表達(dá)式

  • execution(* com.nateshao.jdk. * . * (..)) 是定義的切入點(diǎn)表達(dá)式,該切入點(diǎn)表達(dá)式的意思是匹配com.nateshao.jdk包中任意類的任意方法的執(zhí)行。
  • execution(* com.nateshao.jdk..(..)) :表達(dá)式的主體
  • execution(* :* 表示所有返回類型
  • com.nateshao.jdk:需要攔截的包名字
  • execution(* com.nateshao.jdk. * :* 代表所有類
  • execution(* com.nateshao.jdk. * . * :方法名,使用* 代表所有方法
  • execution(* com.nateshao.jdk..(..)) :. . 表示任意參數(shù)

配置通知

“使用< aop:aspect>的子元素可以配置5種常用通知,這5個(gè)子元素不支持使用子元素,但在使用時(shí)可以指定一些屬性,其常用屬性及其描述如下:

MyAspect.java

  1. package com.nateshao.aspectj.xml; 
  2.  
  3. import org.aspectj.lang.JoinPoint; 
  4. import org.aspectj.lang.ProceedingJoinPoint; 
  5. /** 
  6.  * @date Created by 邵桐杰 on 2021/10/14 19:56 
  7.  * @微信公眾號 程序員千羽 
  8.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  9.  * @博客 https://nateshao.gitee.io 
  10.  * @GitHub https://github.com/nateshao 
  11.  * @Gitee https://gitee.com/nateshao 
  12.  * Description: 切面類,在此類中編寫通知 
  13.  */ 
  14. public class MyAspect { 
  15.     // 前置通知 
  16.     public void myBefore(JoinPoint joinPoint) { 
  17.         System.out.print("前置通知 :模擬執(zhí)行權(quán)限檢查...,"); 
  18.         System.out.print("目標(biāo)類是:"+joinPoint.getTarget() ); 
  19.         System.out.println(",被織入增強(qiáng)處理的目標(biāo)方法為:" 
  20.                 +joinPoint.getSignature().getName()); 
  21.     } 
  22.     // 后置通知 
  23.     public void myAfterReturning(JoinPoint joinPoint) { 
  24.         System.out.print("后置通知:模擬記錄日志...," ); 
  25.         System.out.println("被織入增強(qiáng)處理的目標(biāo)方法為:" 
  26.                 + joinPoint.getSignature().getName()); 
  27.     } 
  28.     /** 
  29.      * 環(huán)繞通知 
  30.      * ProceedingJoinPoint 是JoinPoint子接口,表示可以執(zhí)行目標(biāo)方法 
  31.      * 1.必須是Object類型的返回值 
  32.      * 2.必須接收一個(gè)參數(shù),類型為ProceedingJoinPoint 
  33.      * 3.必須throws Throwable 
  34.      */ 
  35.     public Object myAround(ProceedingJoinPoint proceedingJoinPoint) 
  36.             throws Throwable { 
  37.         // 開始 
  38.         System.out.println("環(huán)繞開始:執(zhí)行目標(biāo)方法之前,模擬開啟事務(wù)..."); 
  39.         // 執(zhí)行當(dāng)前目標(biāo)方法 
  40.         Object obj = proceedingJoinPoint.proceed(); 
  41.         // 結(jié)束 
  42.         System.out.println("環(huán)繞結(jié)束:執(zhí)行目標(biāo)方法之后,模擬關(guān)閉事務(wù)..."); 
  43.         return obj; 
  44.     } 
  45.     // 異常通知 
  46.     public void myAfterThrowing(JoinPoint joinPoint, Throwable e) { 
  47.         System.out.println("異常通知:" + "出錯了" + e.getMessage()); 
  48.     } 
  49.     // 最終通知 
  50.     public void myAfter() { 
  51.         System.out.println("最終通知:模擬方法結(jié)束后的釋放資源..."); 
  52.     } 

config.xml

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  5.    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> 
  6.     <!-- 1 目標(biāo)類 --> 
  7.     <bean id="userDao" class="com.nateshao.jdk.UserDaoImpl" /> 
  8.     <!-- 2 切面類 --> 
  9.     <bean id="myAspect" class="com.nateshao.factorybean.MyAspect" /> 
  10.     <!-- 3 使用Spring代理工廠定義一個(gè)名稱為userDaoProxy的代理對象 --> 
  11.     <bean id="userDaoProxy" 
  12.           class="org.springframework.aop.framework.ProxyFactoryBean"
  13.         <!-- 3.1 指定代理實(shí)現(xiàn)的接口--> 
  14.         <property name="proxyInterfaces" 
  15.                   value="com.nateshao.jdk.UserDao" /> 
  16.         <!-- 3.2 指定目標(biāo)對象 --> 
  17.         <property name="target" ref="userDao" /> 
  18.         <!-- 3.3 指定切面,織入環(huán)繞通知 --> 
  19.         <property name="interceptorNames" value="myAspect" /> 
  20.         <!-- 3.4 指定代理方式,true:使用cglib,false(默認(rèn)):使用jdk動態(tài)代理 --> 
  21.         <property name="proxyTargetClass" value="true" /> 
  22.     </bean> 
  23. </beans> 

 

 

TestXmlAspectj.java

  1. package com.nateshao.aspectj.xml; 
  2.  
  3. import com.nateshao.jdk.UserDao; 
  4. import org.springframework.context.ApplicationContext; 
  5. import org.springframework.context.support.ClassPathXmlApplicationContext; 
  6.  
  7. /** 
  8.  * @date Created by 邵桐杰 on 2021/10/14 19:58 
  9.  * @微信公眾號 程序員千羽 
  10.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  11.  * @博客 https://nateshao.gitee.io 
  12.  * @GitHub https://github.com/nateshao 
  13.  * @Gitee https://gitee.com/nateshao 
  14.  * Description: 
  15.  */ 
  16. public class TestXmlAspectj { 
  17.     public static void main(String args[]) { 
  18.         String xmlPath = 
  19.                 "config.xml"
  20.         ApplicationContext applicationContext = 
  21.                 new ClassPathXmlApplicationContext(xmlPath); 
  22.         // 1 從spring容器獲得內(nèi)容 
  23.         UserDao userDao = (UserDao) applicationContext.getBean("userDao"); 
  24.         // 2 執(zhí)行方法 
  25.         userDao.addUser(); 
  26.     } 

基于注解的聲明式AspectJ(常用)

AspectJ框架為AOP的實(shí)現(xiàn)提供了一套注解,用以取代Spring配置文件中為實(shí)現(xiàn)AOP功能所配置的臃腫代碼。AspectJ的注解及其描述如下所示:

MyAspect.java

  1. package com.nateshao.aspectj.annotation; 
  2.  
  3. import org.aspectj.lang.JoinPoint; 
  4. import org.aspectj.lang.ProceedingJoinPoint; 
  5. import org.aspectj.lang.annotation.*; 
  6. import org.springframework.stereotype.Component; 
  7.  
  8. /** 
  9.  * @date Created by 邵桐杰 on 2021/10/14 20:06 
  10.  * @微信公眾號 程序員千羽 
  11.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  12.  * @博客 https://nateshao.gitee.io 
  13.  * @GitHub https://github.com/nateshao 
  14.  * @Gitee https://gitee.com/nateshao 
  15.  * Description: 切面類,在此類中編寫通知 
  16.  */ 
  17. @Aspect 
  18. @Component 
  19. public class MyAspect { 
  20.     // 定義切入點(diǎn)表達(dá)式 
  21.     @Pointcut("execution(* com.nateshao.jdk.*.*(..))"
  22.     // 使用一個(gè)返回值為void、方法體為空的方法來命名切入點(diǎn) 
  23.     private void myPointCut(){} 
  24.     // 前置通知 
  25.     @Before("myPointCut()"
  26.     public void myBefore(JoinPoint joinPoint) { 
  27.         System.out.print("前置通知 :模擬執(zhí)行權(quán)限檢查...,"); 
  28.         System.out.print("目標(biāo)類是:"+joinPoint.getTarget() ); 
  29.         System.out.println(",被織入增強(qiáng)處理的目標(biāo)方法為:" 
  30.                 +joinPoint.getSignature().getName()); 
  31.     } 
  32.     // 后置通知 
  33.     @AfterReturning(value="myPointCut()"
  34.     public void myAfterReturning(JoinPoint joinPoint) { 
  35.         System.out.print("后置通知:模擬記錄日志...," ); 
  36.         System.out.println("被織入增強(qiáng)處理的目標(biāo)方法為:" 
  37.                 + joinPoint.getSignature().getName()); 
  38.     } 
  39.     // 環(huán)繞通知 
  40.     @Around("myPointCut()"
  41.     public Object myAround(ProceedingJoinPoint proceedingJoinPoint) 
  42.             throws Throwable { 
  43.         // 開始 
  44.         System.out.println("環(huán)繞開始:執(zhí)行目標(biāo)方法之前,模擬開啟事務(wù)..."); 
  45.         // 執(zhí)行當(dāng)前目標(biāo)方法 
  46.         Object obj = proceedingJoinPoint.proceed(); 
  47.         // 結(jié)束 
  48.         System.out.println("環(huán)繞結(jié)束:執(zhí)行目標(biāo)方法之后,模擬關(guān)閉事務(wù)..."); 
  49.         return obj; 
  50.     } 
  51.     // 異常通知 
  52.     @AfterThrowing(value="myPointCut()",throwing="e"
  53.     public void myAfterThrowing(JoinPoint joinPoint, Throwable e) { 
  54.         System.out.println("異常通知:" + "出錯了" + e.getMessage()); 
  55.     } 
  56.     // 最終通知 
  57.     @After("myPointCut()"
  58.     public void myAfter() { 
  59.         System.out.println("最終通知:模擬方法結(jié)束后的釋放資源..."); 
  60.     } 

annotation.xml

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:aop="http://www.springframework.org/schema/aop" 
  5.        xmlns:context="http://www.springframework.org/schema/context" 
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  7.   http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
  8.   http://www.springframework.org/schema/aop 
  9.   http://www.springframework.org/schema/aop/spring-aop-4.3.xsd 
  10.   http://www.springframework.org/schema/context 
  11.   http://www.springframework.org/schema/context/spring-context-4.3.xsd"> 
  12.     <!-- 指定需要掃描的包,使注解生效 --> 
  13.     <context:component-scan base-package="com.nateshao" /> 
  14.     <!-- 啟動基于注解的聲明式AspectJ支持 --> 
  15.     <aop:aspectj-autoproxy /> 
  16. </beans> 

 

TestAnnotationAspectj.java

  1. package com.nateshao.aspectj.annotation; 
  2.  
  3. import com.nateshao.jdk.UserDao; 
  4. import org.springframework.context.ApplicationContext; 
  5. import org.springframework.context.support.ClassPathXmlApplicationContext; 
  6. /** 
  7.  * @date Created by 邵桐杰 on 2021/10/14 20:09 
  8.  * @微信公眾號 程序員千羽 
  9.  * @個(gè)人網(wǎng)站 www.nateshao.cn 
  10.  * @博客 https://nateshao.gitee.io 
  11.  * @GitHub https://github.com/nateshao 
  12.  * @Gitee https://gitee.com/nateshao 
  13.  * Description: 
  14.  */ 
  15. public class TestAnnotationAspectj { 
  16.     public static void main(String args[]) { 
  17.         String xmlPath = "annotation.xml"
  18.         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); 
  19.         // 1 從spring容器獲得內(nèi)容 
  20.         UserDao userDao = (UserDao) applicationContext.getBean("userDao"); 
  21.         // 2 執(zhí)行方法 
  22.         userDao.addUser(); 
  23.     } 

總結(jié)

這篇文章主要講解了Spring框架中AOP的相關(guān)知識。

  • 首先對AOP進(jìn)行了簡單的介紹,
  • 然后講解了Spring中的兩種動態(tài)代理,
  • 接下來講解了Spring中基于代理類的AOP實(shí)現(xiàn),
  • 最后講解了如何使用AspectJ框架來進(jìn)行AOP開發(fā)。

通過本章的學(xué)習(xí),我們可以了解AOP的概念和作用,理解AOP中的相關(guān)常用術(shù)語,熟悉Spring中兩種動態(tài)代理方式的區(qū)別,并能夠掌握基于代理類和AspectJ框架的AOP開發(fā)方式。

 

責(zé)任編輯:武曉燕 來源: 程序員千羽
相關(guān)推薦

2024-05-28 00:00:03

Java垃圾收集機(jī)制

2021-07-27 18:03:59

iOSSwift調(diào)度器

2022-05-07 07:43:07

Redis存儲系統(tǒng)數(shù)據(jù)庫

2021-07-14 08:00:12

Numa架構(gòu)Linux

2021-11-29 07:24:08

ACID事務(wù)大數(shù)據(jù)

2023-06-30 08:27:20

2017-11-15 08:50:59

數(shù)據(jù)庫MySQL執(zhí)

2010-04-01 13:58:16

WinCE 6.0Cashmere

2022-07-20 08:55:10

編輯器VueTiptap

2022-12-06 08:12:11

Java關(guān)鍵字

2020-07-23 07:51:51

Python編程語言工具

2023-05-09 07:51:28

Spring循環(huán)依賴

2023-10-26 08:38:43

SQL排名平分分區(qū)

2022-02-22 10:50:19

IDEAGit工具,

2017-01-22 15:09:08

架構(gòu)閉環(huán)演進(jìn)

2023-04-26 07:30:00

promptUI非結(jié)構(gòu)化

2022-10-08 00:00:05

SQL機(jī)制結(jié)構(gòu)

2022-03-08 17:52:58

TCP格式IP

2024-02-20 21:34:16

循環(huán)GolangGo

2021-08-27 07:06:10

IOJava抽象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

久久av网站| 午夜精品在线播放| 亚州综合一区| 日韩欧美在线免费| 日韩国产精品一区二区三区| 日韩欧美在线观看免费| 日韩欧美精品综合| 欧美一级在线免费| 欧美极品欧美精品欧美| 手机福利在线| 美女网站色91| 欧美xxxx做受欧美| 中国xxxx性xxxx产国| 成人勉费视频| 国产日产亚洲精品系列| 成人妇女免费播放久久久| 久久国产精品二区| 免费一区二区三区视频导航| 欧美日韩精品是欧美日韩精品| 国产一二三四区在线观看| 西西人体44www大胆无码| 久久综合影视| 欧美国产视频一区二区| 欧美狂猛xxxxx乱大交3| 久久国产精品免费一区二区三区| 精品久久久中文| 一区二区三区国| 色窝窝无码一区二区三区成人网站| 丝袜亚洲另类欧美| 成年无码av片在线| av网在线播放| 国产精品jk白丝蜜臀av小说 | 中文字幕美女视频| 精品午夜视频| 色婷婷精品大在线视频| 日韩视频 中文字幕| av中文字幕在线| 成人aa视频在线观看| 国产精品永久在线| 男女视频免费看| 中文在线播放一区二区| 精品偷拍各种wc美女嘘嘘| 亚洲综合123| 韩国理伦片久久电影网| 精品久久久视频| www.一区二区.com| 欧美三级理伦电影| 国产天堂亚洲国产碰碰| 粉嫩av四季av绯色av第一区| 亚洲天堂网在线观看视频| 一区二区三区导航| 欧美精品videossex性护士| 亚洲综合第一区| 亚洲欧美tv| 日韩精品www| 91香蕉国产线在线观看| 久久人人视频| 欧美视频第二页| 日韩无套无码精品| 婷婷激情一区| 亚洲成人免费观看| 免费极品av一视觉盛宴| 麻豆视频网站在线观看| 国产精品污www在线观看| 免费成人深夜夜行视频| 黄色av免费观看| www.久久久久久久久| 99在线观看视频| www.久久久久久久久久| 日韩成人av影视| 国产精品草莓在线免费观看| 精品人妻无码一区二区性色| 一二三区精品| 热门国产精品亚洲第一区在线| 日韩精品一区二区av| 欧美日韩爆操| 日韩小视频网址| 999精品视频在线观看播放| 久久精品不卡| 久久国产一区二区三区| www.xx日本| 中文字幕一区二区精品区| 久久亚洲欧美日韩精品专区| 91九色丨porny丨极品女神| 伊人久久大香线| 欧美高清videos高潮hd| 国产中文字字幕乱码无限| 激情五月***国产精品| 欧美国产乱视频| 国产超碰人人爽人人做人人爱| 香蕉久久国产| 国产精品久久久久免费a∨大胸| 欧美 亚洲 另类 激情 另类| 看片的网站亚洲| 亚洲一区二区三区视频| 黄色小视频免费观看| 99久久综合国产精品| 欧美午夜精品久久久久免费视| 国产香蕉视频在线看| 国产精品传媒视频| 蜜臀av无码一区二区三区| 中文字幕影音在线| 欧美日韩中字一区| 国产精品19p| 日韩电影不卡一区| 日韩在线观看视频免费| 久久久久久久久久一区二区三区| 一本色道久久综合亚洲精品不| 国产精品91在线| 国产内射老熟女aaaa∵| 99在线热播精品免费| 亚洲乱码一区二区三区| 在线观看中文| 午夜成人免费电影| 在线观看免费的av| www.久久东京| 综合136福利视频在线| 久久久久亚洲av无码专区| 久久精品女人天堂| 99视频在线免费观看| 高清美女视频一区| 亚洲一区二区三区四区在线观看 | 精品少妇无遮挡毛片| 久久av影院| 精品国产成人系列| 网站永久看片免费| 中文精品在线| 91精品国产一区二区三区动漫 | 久久av无码精品人妻系列试探| 99久久精品费精品国产风间由美| 91精品国产免费久久久久久| 国产女人爽到高潮a毛片| 久久婷婷综合激情| 999久久欧美人妻一区二区| 国产精品字幕| 日韩电影视频免费| 久草福利资源在线观看| 久久精品999| 痴汉一区二区三区| 日本视频在线观看| 日本乱人伦一区| 捆绑裸体绳奴bdsm亚洲| 91高清一区| 91国产视频在线| 精品久久久免费视频| 国产欧美一区二区精品仙草咪| 污污污污污污www网站免费| 久久精品资源| 日韩www在线| 免费中文字幕在线观看| 国产一区二区在线免费观看| 久久久久久久久久久久久久一区 | 日韩视频一区| 99久久免费国| 91精品久久| 884aa四虎影成人精品一区| 99精品全国免费观看| 亚洲欧美日韩国产一区| 韩国成人av| 欧美1—12sexvideos| 555www色欧美视频| 青花影视在线观看免费高清| 国产亚洲一级| 久久九九视频| 欧美18av| 亚洲福利精品在线| 91看片在线播放| 91视频.com| 日本wwww视频| 欧美男男gaytwinkfreevideos| 97香蕉久久夜色精品国产| 男人天堂av网| 欧美三级欧美成人高清www| 可以直接看的无码av| 激情丁香综合| 韩日午夜在线资源一区二区| 欧美私密网站| 伊人男人综合视频网| 日韩欧美一级大片| 中文字幕在线观看一区二区| 午夜视频在线网站| 欧美 日韩 国产精品免费观看| 91理论片午午论夜理片久久| 亚洲丝袜一区| 亚洲精品福利在线观看| 久久久久久少妇| 国产嫩草影院久久久久| 日本激情视频在线播放| 99久久综合| 成人高清在线观看| 国产社区精品视频| 欧美精品一区二区三区视频| www.久久久久久久| 国产精品久久久久久久久快鸭| 国产探花在线观看视频| 在线成人www免费观看视频| 鬼打鬼之黄金道士1992林正英| av电影在线地址| 亚洲欧美三级伦理| 一区二区三区精彩视频| 亚洲一区中文日韩| 亚洲av无码一区二区二三区| 麻豆成人久久精品二区三区红 | 亚洲欧美区自拍先锋| av在线天堂网| 久久久久.com| 中文字幕乱码免费| 天天操综合520| 日韩精品专区在线| 国产九色在线播放九色| 亚洲蜜桃精久久久久久久| 中文在线一区二区三区| 国产精品综合av一区二区国产馆| 成年人在线看片| 国内精品美女在线观看| 综合视频免费看| 久久99国产成人小视频| 国产精品福利视频| 国产精品va视频| 国产精品视频xxx| 日韩国产激情| 午夜精品久久17c| 91麻豆免费在线视频| 伊人久久久久久久久久| 日本在线视频1区| 亚洲精品一线二线三线| a在线观看视频| 91精品久久久久久久91蜜桃 | 手机av免费在线| 日韩中文字幕网| av中文字幕一区二区三区| 亚洲美女av在线播放| 日韩有码第一页| 精品日韩一区二区三区| a级片免费视频| 91麻豆精品国产无毒不卡在线观看| 成人黄色激情视频| 在线中文字幕一区二区| 国产一级18片视频| 精品欧美aⅴ在线网站| 日韩成人一区二区三区| 亚洲高清一区二区三区| 国产一国产二国产三| 亚洲伊人伊色伊影伊综合网| 欧美交换国产一区内射| 一区二区三区日韩欧美| 婷婷色中文字幕| 一区二区三区四区在线免费观看| 亚洲精品国产精品国自产网站| 久久你懂得1024| 精品人妻互换一区二区三区| 91免费视频大全| 无码人妻精品一区二区三区温州| 91在线丨porny丨国产| 免费无码一区二区三区| 久久久国产一区二区三区四区小说| 毛片网站免费观看| 国产三区在线成人av| 亚洲女同二女同志奶水| 综合精品久久久| 免费在线视频一区二区| 五月婷婷综合激情| 无码视频一区二区三区| 一本色道亚洲精品aⅴ| 成人午夜精品视频| www.色.com| 亚洲国产一区二区精品专区| 日韩欧美视频免费在线观看| 亚洲欧美一区在线| 久久成人福利视频| 国产精品嫩草99av在线| 久久久精品麻豆| 捆绑调教美女网站视频一区| 无码人妻一区二区三区在线视频| 国产不卡在线一区| 黄色短视频在线观看| 国产欧美一区二区三区网站 | 最近2019中文免费高清视频观看www99 | 国精产品久拍自产在线网站| 一区二区三区在线视频观看58| 久久午夜无码鲁丝片午夜精品| 欧美日韩国产丝袜另类| 久久久999久久久| 88在线观看91蜜桃国自产| 欧洲精品久久一区二区| 亚洲深夜福利视频| www久久日com| 欧美一区二区色| 欧美亚洲二区| 国产日韩欧美一区二区| 精品国产欧美日韩| 久久亚洲国产成人精品无码区| 亚洲视频二区| www.日本久久| 久久嫩草精品久久久精品| 夫妻性生活毛片| 精品美女永久免费视频| 一级片免费网站| 亚洲精品电影网| 超碰电影在线播放| 日韩美女激情视频| 1204国产成人精品视频| 日韩欧美视频一区二区三区四区| 国产精品啊啊啊| 鲁一鲁一鲁一鲁一av| 99精品一区二区三区| 岛国片在线免费观看| 亚洲成人www| 国产精品久久久久久久一区二区| 精品无人区太爽高潮在线播放| www在线免费观看视频| 国产精品aaa| 欧美美女在线直播| 992tv快乐视频| 看片的网站亚洲| 精品无人区无码乱码毛片国产 | 久久99精品波多结衣一区| 日韩一级黄色片| 中文字幕日本在线| 欧美中文字幕视频| 高清精品xnxxcom| 国产人妻互换一区二区| 日本欧美一区二区三区乱码| 西西大胆午夜视频| 亚洲自拍欧美精品| 国产麻豆免费观看| 少妇av一区二区三区| 激情开心成人网| 久久综合九色欧美狠狠| 激情文学一区| 老熟女高潮一区二区三区| 自拍偷拍国产亚洲| 中文字幕欧美色图| 亚洲一区www| 免费观看欧美大片| 久久精品人成| 中文一区二区| 少妇一级淫片免费放播放| 亚洲线精品一区二区三区八戒| 国产熟女一区二区丰满| 久久人人爽亚洲精品天堂| 国产精品原创视频| 亚洲欧美日韩国产yyy| 日韩国产成人精品| 阿v天堂2014| 精品婷婷伊人一区三区三| 国产高清在线| 国产精品免费观看在线| 欧美日韩在线播放视频| 污网站免费在线| 国产精品乱人伦一区二区| 亚洲无码精品国产| 最近2019中文字幕在线高清 | 欧美日韩中文精品| 毛片在线播放a| 91九色在线免费视频| 好吊一区二区三区| 污污污www精品国产网站| 精品国产福利视频| 日韩av资源| 国产精品劲爆视频| 成人综合一区| 四虎成人在线播放| 亚洲一区二区四区蜜桃| 天天av综合网| 国产精品精品久久久久久| 日韩精品中文字幕第1页| 极品粉嫩美女露脸啪啪| 一区二区三区在线看| 天堂中文在线资源| 国产精品99久久久久久人| 97精品中文字幕| 亚洲天堂av网站| 在线观看中文字幕不卡| 免费在线观看av片| 国产精品高清一区二区三区| 亚洲欧美网站| 国产又粗又长又黄的视频| 欧美成人三级电影在线| 亚洲免费福利| 国产a级片免费看| 成人99免费视频| 日本黄色一级视频| 伦理中文字幕亚洲| 久久精品国产亚洲blacked| 黄色av免费在线播放| 亚洲视频一区在线| 少妇激情av一区二区| 国产精品久久久久久久久久久久 | 国产精品久久久久久久久免费桃花 | 性xxxxfjsxxxxx欧美| 欧美lavv| 国产酒店精品激情| 精品久久久久久久久久久久久久久久久久| 日韩一区视频在线| 日韩高清影视在线观看| 亚洲男人天堂av在线| 欧美视频二区36p| 国产福利视频在线| 欧美一区1区三区3区公司|