成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我們一起了解 Spring 中的 AOP !

開發 架構
AOP的全稱是Aspect-Oriented Programming,即面向切面編程(也稱面向方面編程)。它是面向對象編程(OOP)的一種補充,目前已成為一種比較成熟的編程方式。

[[431585]]

本文轉載自微信公眾號「程序員千羽」,作者程序員千羽 。轉載本文請聯系程序員千羽公眾號。

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

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

1. Spring AOP簡介

什么是AOP?

AOP的全稱是Aspect-Oriented Programming,即面向切面編程(也稱面向方面編程)。它是面向對象編程(OOP)的一種補充,目前已成為一種比較成熟的編程方式。

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

為了解決這一問題,AOP思想隨之產生。AOP采取橫向抽取機制,將分散在各個方法中的重復代碼提取出來,然后在程序編譯或運行時,再將這些提取出來的代碼應用到需要執行的地方。這種采用橫向抽取機制的方式,采用傳統的OOP思想顯然是無法辦到的,因為OOP只能實現父子關系的縱向的重用。雖然AOP是一種新的編程思想,但卻不是OOP的替代品,它只是OOP的延伸和補充。

類與切面的關系

AOP的使用,使開發人員在編寫業務邏輯時可以專心于核心業務,而不用過多的關注于其他業務邏輯的實現,這不但提高了開發效率,而且增強了代碼的可維護性。

Proxy(代理):將通知應用到目標對象之后,被動態創建的對象。

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

2. 動態代理

jdk動態代理

“JDK動態代理是通過java.lang.reflect.Proxy 類來實現的,我們可以調用Proxy類的newProxyInstance()方法來創建代理對象。對于使用業務接口的類,Spring默認會使用JDK動態代理來實現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.  * @個人網站 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.  * @個人網站 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.     // 聲明目標類接口 
  19.     private UserDao userDao; 
  20.     // 創建代理方法 
  21.     public  Object createProxy(UserDao userDao) { 
  22.         this.userDao = userDao; 
  23.         // 1.類加載器 
  24.         ClassLoader classLoader = JdkProxy.class.getClassLoader(); 
  25.         // 2.被代理對象實現的所有接口 
  26.         Class[] clazz = userDao.getClass().getInterfaces(); 
  27.         // 3.使用代理類,進行增強,返回的是代理后的對象 
  28.         return  Proxy.newProxyInstance(classLoader,clazz,this); 
  29.     } 
  30.  
  31.     /** 
  32.      * 所有動態代理類的方法調用,都會交由invoke()方法去處理 
  33.      * @param proxy 被代理后的對象 
  34.      * @param method 將要被執行的方法信息(反射) 
  35.      * @param args 執行方法時需要的參數 
  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.         // 前增強 
  45.         myAspect.check_Permissions(); 
  46.         // 在目標類上調用方法,并傳入參數 
  47.         Object obj = method.invoke(userDao, args); 
  48.         // 后增強 
  49.         myAspect.log(); 
  50.         return obj; 
  51.     } 

CGLIB代理

通過前面的學習可知,JDK的動態代理用起來非常簡單,但它是有局限性的,使用動態代理的對象必須實現一個或多個接口。

如果想代理沒有實現接口的類,那么可以使用CGLIB代理。

“CGLIB(Code Generation Library)是一個高性能開源的代碼生成包,它采用非常底層的字節碼技術,對指定的目標類生成一個子類,并對子類進行增強。

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.  * @個人網站 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.         // 創建一個動態類對象 
  23.         Enhancer enhancer = new Enhancer(); 
  24.         // 確定需要增強的類,設置其父類 
  25.         enhancer.setSuperclass(target.getClass()); 
  26.         // 添加回調函數 
  27.         enhancer.setCallback(this); 
  28.         // 返回創建的代理類 
  29.         return enhancer.create(); 
  30.     } 
  31.  
  32.     /** 
  33.      * @param proxy CGlib根據指定父類生成的代理對象 
  34.      * @param method 攔截的方法 
  35.      * @param args 攔截方法的參數數組 
  36.      * @param methodProxy 方法的代理對象,用于執行父類的方法 
  37.      * @return 
  38.      * @throws Throwable 
  39.      */ 
  40.     @Override 
  41.     public Object intercept(Object proxy, Method method, Object[] args, 
  42.                             MethodProxy methodProxy) throws Throwable { 
  43.         // 創建切面類對象 
  44.         MyAspect myAspect = new MyAspect(); 
  45.         // 前增強 
  46.         myAspect.check_Permissions(); 
  47.         // 目標方法執行 
  48.         Object obj = methodProxy.invokeSuper(proxy, args); 
  49.         // 后增強 
  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.  * @個人網站 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.         // 創建代理對象 
  15.         CglibProxy cglibProxy = new CglibProxy(); 
  16.         // 創建目標對象 
  17.         UserDao userDao = new UserDao(); 
  18.         // 獲取增強后的目標對象 
  19.         UserDao userDao1 = (UserDao)cglibProxy.createProxy(userDao); 
  20.         // 執行方法 
  21.         userDao1.addUser(); 
  22.         userDao1.deleteUser(); 
  23.     } 

3. 基于代理類的AOP實現

Spring的通知類型

Spring按照通知在目標類方法的連接點位置,可以分為5種類型,具體如下:

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

在目標方法執行前實施增強,可以應用于權限管理等功能。

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

在目標方法執行后實施增強,可以應用于關閉流、上傳文件、刪除臨時文件等功能。

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

在目標方法執行前后實施增強,可以應用于日志、事務管理等功能。

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

在方法拋出異常后實施增強,可以應用于處理異常記錄日志等功能。

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

在目標類中添加一些新的方法和屬性,可以應用于修改老版本程序。

ProxyFactoryBean

“ProxyFactoryBean是FactoryBean接口的實現類,FactoryBean負責實例化一個Bean,而ProxyFactoryBean負責為其他Bean創建代理實例。在Spring中,使用ProxyFactoryBean是創建AOP代理的基本方式。

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

代碼實現

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.  * @個人網站 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.         // 執行目標方法 
  21.         Object obj = mi.proceed(); 
  22.         log(); 
  23.         return obj; 
  24.     } 
  25.     public void check_Permissions(){ 
  26.         System.out.println("模擬檢查權限..."); 
  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 目標類 --> 
  7.     <bean id="userDao" class="com.nateshao.jdk.UserDaoImpl" /> 
  8.     <!-- 2 切面類 --> 
  9.     <bean id="myAspect" class="com.nateshao.factorybean.MyAspect" /> 
  10.     <!-- 3 使用Spring代理工廠定義一個名稱為userDaoProxy的代理對象 --> 
  11.     <bean id="userDaoProxy" 
  12.           class="org.springframework.aop.framework.ProxyFactoryBean"
  13.         <!-- 3.1 指定代理實現的接口--> 
  14.         <property name="proxyInterfaces" 
  15.                   value="com.nateshao.jdk.UserDao" /> 
  16.         <!-- 3.2 指定目標對象 --> 
  17.         <property name="target" ref="userDao" /> 
  18.         <!-- 3.3 指定切面,織入環繞通知 --> 
  19.         <property name="interceptorNames" value="myAspect" /> 
  20.         <!-- 3.4 指定代理方式,true:使用cglib,false(默認):使用jdk動態代理 --> 
  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.  * @個人網站 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容器獲得內容 
  21.         UserDao userDao = (UserDao) applicationContext.getBean("userDaoProxy"); 
  22.         // 執行方法 
  23.         userDao.addUser(); 
  24.         userDao.deleteUser(); 
  25.     } 

4. AspectJ開發

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

基于XML的聲明式AspectJ

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

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

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

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 >元素,該元素會將一個已定義好的Spring Bean轉換成切面Bean,所以要在配置文件中先定義一個普通的Spring Bean。

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

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

配置切入點

“當< aop:pointcut>元素作為< aop:config>元素的子元素定義時,表示該切入點是全局切入點,它可被多個切面所共享;當< aop:pointcut>元素作為< aop:aspect>元素的子元素時,表示該切入點只對當前切面有效。

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

id:用于指定切入點的唯-標識名稱。. expressione:用于指定切入點關聯的切入點表達式

切入點表達式

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

配置通知

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

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.  * @個人網站 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("前置通知 :模擬執行權限檢查...,"); 
  18.         System.out.print("目標類是:"+joinPoint.getTarget() ); 
  19.         System.out.println(",被織入增強處理的目標方法為:" 
  20.                 +joinPoint.getSignature().getName()); 
  21.     } 
  22.     // 后置通知 
  23.     public void myAfterReturning(JoinPoint joinPoint) { 
  24.         System.out.print("后置通知:模擬記錄日志...," ); 
  25.         System.out.println("被織入增強處理的目標方法為:" 
  26.                 + joinPoint.getSignature().getName()); 
  27.     } 
  28.     /** 
  29.      * 環繞通知 
  30.      * ProceedingJoinPoint 是JoinPoint子接口,表示可以執行目標方法 
  31.      * 1.必須是Object類型的返回值 
  32.      * 2.必須接收一個參數,類型為ProceedingJoinPoint 
  33.      * 3.必須throws Throwable 
  34.      */ 
  35.     public Object myAround(ProceedingJoinPoint proceedingJoinPoint) 
  36.             throws Throwable { 
  37.         // 開始 
  38.         System.out.println("環繞開始:執行目標方法之前,模擬開啟事務..."); 
  39.         // 執行當前目標方法 
  40.         Object obj = proceedingJoinPoint.proceed(); 
  41.         // 結束 
  42.         System.out.println("環繞結束:執行目標方法之后,模擬關閉事務..."); 
  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("最終通知:模擬方法結束后的釋放資源..."); 
  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 目標類 --> 
  7.     <bean id="userDao" class="com.nateshao.jdk.UserDaoImpl" /> 
  8.     <!-- 2 切面類 --> 
  9.     <bean id="myAspect" class="com.nateshao.factorybean.MyAspect" /> 
  10.     <!-- 3 使用Spring代理工廠定義一個名稱為userDaoProxy的代理對象 --> 
  11.     <bean id="userDaoProxy" 
  12.           class="org.springframework.aop.framework.ProxyFactoryBean"
  13.         <!-- 3.1 指定代理實現的接口--> 
  14.         <property name="proxyInterfaces" 
  15.                   value="com.nateshao.jdk.UserDao" /> 
  16.         <!-- 3.2 指定目標對象 --> 
  17.         <property name="target" ref="userDao" /> 
  18.         <!-- 3.3 指定切面,織入環繞通知 --> 
  19.         <property name="interceptorNames" value="myAspect" /> 
  20.         <!-- 3.4 指定代理方式,true:使用cglib,false(默認):使用jdk動態代理 --> 
  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.  * @個人網站 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容器獲得內容 
  23.         UserDao userDao = (UserDao) applicationContext.getBean("userDao"); 
  24.         // 2 執行方法 
  25.         userDao.addUser(); 
  26.     } 

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

AspectJ框架為AOP的實現提供了一套注解,用以取代Spring配置文件中為實現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.  * @個人網站 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.     // 定義切入點表達式 
  21.     @Pointcut("execution(* com.nateshao.jdk.*.*(..))"
  22.     // 使用一個返回值為void、方法體為空的方法來命名切入點 
  23.     private void myPointCut(){} 
  24.     // 前置通知 
  25.     @Before("myPointCut()"
  26.     public void myBefore(JoinPoint joinPoint) { 
  27.         System.out.print("前置通知 :模擬執行權限檢查...,"); 
  28.         System.out.print("目標類是:"+joinPoint.getTarget() ); 
  29.         System.out.println(",被織入增強處理的目標方法為:" 
  30.                 +joinPoint.getSignature().getName()); 
  31.     } 
  32.     // 后置通知 
  33.     @AfterReturning(value="myPointCut()"
  34.     public void myAfterReturning(JoinPoint joinPoint) { 
  35.         System.out.print("后置通知:模擬記錄日志...," ); 
  36.         System.out.println("被織入增強處理的目標方法為:" 
  37.                 + joinPoint.getSignature().getName()); 
  38.     } 
  39.     // 環繞通知 
  40.     @Around("myPointCut()"
  41.     public Object myAround(ProceedingJoinPoint proceedingJoinPoint) 
  42.             throws Throwable { 
  43.         // 開始 
  44.         System.out.println("環繞開始:執行目標方法之前,模擬開啟事務..."); 
  45.         // 執行當前目標方法 
  46.         Object obj = proceedingJoinPoint.proceed(); 
  47.         // 結束 
  48.         System.out.println("環繞結束:執行目標方法之后,模擬關閉事務..."); 
  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("最終通知:模擬方法結束后的釋放資源..."); 
  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.  * @個人網站 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容器獲得內容 
  20.         UserDao userDao = (UserDao) applicationContext.getBean("userDao"); 
  21.         // 2 執行方法 
  22.         userDao.addUser(); 
  23.     } 

總結

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

  • 首先對AOP進行了簡單的介紹,
  • 然后講解了Spring中的兩種動態代理,
  • 接下來講解了Spring中基于代理類的AOP實現,
  • 最后講解了如何使用AspectJ框架來進行AOP開發。

通過本章的學習,我們可以了解AOP的概念和作用,理解AOP中的相關常用術語,熟悉Spring中兩種動態代理方式的區別,并能夠掌握基于代理類和AspectJ框架的AOP開發方式。

 

責任編輯:武曉燕 來源: 程序員千羽
相關推薦

2024-05-28 00:00:03

Java垃圾收集機制

2021-07-27 18:03:59

iOSSwift調度器

2022-05-07 07:43:07

Redis存儲系統數據庫

2021-07-14 08:00:12

Numa架構Linux

2021-11-29 07:24:08

ACID事務大數據

2023-06-30 08:27:20

2017-11-15 08:50:59

數據庫MySQL

2010-04-01 13:58:16

WinCE 6.0Cashmere

2022-07-20 08:55:10

編輯器VueTiptap

2022-12-06 08:12:11

Java關鍵字

2020-07-23 07:51:51

Python編程語言工具

2023-05-09 07:51:28

Spring循環依賴

2023-10-26 08:38:43

SQL排名平分分區

2022-02-22 10:50:19

IDEAGit工具,

2022-10-08 00:00:05

SQL機制結構

2017-01-22 15:09:08

架構閉環演進

2023-04-26 07:30:00

promptUI非結構化

2022-03-31 18:59:43

數據庫InnoDBMySQL

2023-08-10 08:28:46

網絡編程通信

2021-08-27 07:06:09

DubboDocker技術
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品久 | 午夜在线| 日韩精品一区二区三区中文在线 | 久久影院一区 | 91视频国产精品 | 在线观看中文字幕亚洲 | 久久国产精品视频 | 亚洲欧洲小视频 | 国产最新网址 | 中文字幕一区二区三区乱码在线 | 精品亚洲永久免费精品 | 欧美一区二区在线播放 | 日韩精品一区二区三区视频播放 | 男人的天堂中文字幕 | 一区二区三区国产精品 | 国产一级特黄视频 | 国产精品久久久久久久久图文区 | 日批的视频 | 性一交一乱一伦视频免费观看 | 久久久久久久久久久久久久久久久久久久 | 国产日韩欧美一区二区 | 男人天堂视频在线观看 | 精品国产一区二区三区免费 | 午夜国产精品视频 | 荷兰欧美一级毛片 | 在线免费观看黄色网址 | 国产精品欧美一区二区三区不卡 | 日韩中文字幕一区 | 成人精品一区亚洲午夜久久久 | 日韩久久久久久久久久久 | 欧美日韩国产传媒 | 日韩伦理一区二区 | 永久精品 | 二区久久 | 欧美性生活免费 | 亚洲精品一级 | 亚洲精品视 | 亚洲国产免费 | 欧美精品一区二区三区四区 在线 | 亚洲精品久久久久中文字幕欢迎你 | 亚洲一区欧美 |