偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

我們一起了解 Spring 中的 AOP !

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

[[431585]]

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

  • 1. Spring AOP簡(jiǎn)介
  • 2. 動(dòng)態(tài)代理
  • jdk動(dòng)態(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簡(jiǎn)介

什么是AOP?

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

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

為了解決這一問題,AOP思想隨之產(chǎn)生。AOP采取橫向抽取機(jī)制,將分散在各個(gè)方法中的重復(fù)代碼提取出來,然后在程序編譯或運(yùn)行時(shí),再將這些提取出來的代碼應(yīng)用到需要執(zhí)行的地方。這種采用橫向抽取機(jī)制的方式,采用傳統(tǒng)的OOP思想顯然是無(wú)法辦到的,因?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)對(duì)象之后,被動(dòng)態(tài)創(chuàng)建的對(duì)象。

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

2. 動(dòng)態(tài)代理

jdk動(dòng)態(tài)代理

“JDK動(dòng)態(tài)代理是通過java.lang.reflect.Proxy 類來實(shí)現(xiàn)的,我們可以調(diào)用Proxy類的newProxyInstance()方法來創(chuàng)建代理對(duì)象。對(duì)于使用業(yè)務(wù)接口的類,Spring默認(rèn)會(huì)使用JDK動(dòng)態(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.  * @微信公眾號(hào) 程序員千羽 
  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.  * @微信公眾號(hào) 程序員千羽 
  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.被代理對(duì)象實(shí)現(xiàn)的所有接口 
  26.         Class[] clazz = userDao.getClass().getInterfaces(); 
  27.         // 3.使用代理類,進(jìn)行增強(qiáng),返回的是代理后的對(duì)象 
  28.         return  Proxy.newProxyInstance(classLoader,clazz,this); 
  29.     } 
  30.  
  31.     /** 
  32.      * 所有動(dòng)態(tài)代理類的方法調(diào)用,都會(huì)交由invoke()方法去處理 
  33.      * @param proxy 被代理后的對(duì)象 
  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的動(dòng)態(tài)代理用起來非常簡(jiǎn)單,但它是有局限性的,使用動(dòng)態(tài)代理的對(duì)象必須實(shí)現(xiàn)一個(gè)或多個(gè)接口。

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

“CGLIB(Code Generation Library)是一個(gè)高性能開源的代碼生成包,它采用非常底層的字節(jié)碼技術(shù),對(duì)指定的目標(biāo)類生成一個(gè)子類,并對(duì)子類進(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.  * @微信公眾號(hào) 程序員千羽 
  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è)動(dòng)態(tài)類對(duì)象 
  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ù)指定父類生成的代理對(duì)象 
  34.      * @param method 攔截的方法 
  35.      * @param args 攔截方法的參數(shù)數(shù)組 
  36.      * @param methodProxy 方法的代理對(duì)象,用于執(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)建切面類對(duì)象 
  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.  * @微信公眾號(hào) 程序員千羽 
  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)建代理對(duì)象 
  15.         CglibProxy cglibProxy = new CglibProxy(); 
  16.         // 創(chuàng)建目標(biāo)對(duì)象 
  17.         UserDao userDao = new UserDao(); 
  18.         // 獲取增強(qiáng)后的目標(biāo)對(duì)象 
  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.  * @微信公眾號(hào) 程序員千羽 
  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的代理對(duì)象 --> 
  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)對(duì)象 --> 
  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動(dòng)態(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.  * @微信公眾號(hào) 程序員千羽 
  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: 測(cè)試類 
  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語(yǔ)言的AOP框架,它提供了強(qiáng)大的AOP功能。Spring 2.0以后,Spring AOP引入了對(duì)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 >元素,該元素會(huì)將一個(gè)已定義好的Spring Bean轉(zhuǎn)換成切面Bean,所以要在配置文件中先定義一個(gè)普通的Spring Bean。

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

id:用于定義該切面的唯一標(biāo)識(shí)名稱。 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)只對(duì)當(dāng)前切面有效。

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

id:用于指定切入點(diǎn)的唯-標(biāo)識(shí)名稱。. 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.  * @微信公眾號(hào) 程序員千羽 
  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("異常通知:" + "出錯(cuò)了" + 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的代理對(duì)象 --> 
  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)對(duì)象 --> 
  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動(dòng)態(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.  * @微信公眾號(hào) 程序員千羽 
  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.  * @微信公眾號(hào) 程序員千羽 
  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("異常通知:" + "出錯(cuò)了" + 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.     <!-- 啟動(dòng)基于注解的聲明式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.  * @微信公眾號(hào) 程序員千羽 
  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)知識(shí)。

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

通過本章的學(xué)習(xí),我們可以了解AOP的概念和作用,理解AOP中的相關(guān)常用術(shù)語(yǔ),熟悉Spring中兩種動(dòng)態(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存儲(chǔ)系統(tǒng)數(shù)據(jù)庫(kù)

2021-11-29 07:24:08

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

2021-07-14 08:00:12

Numa架構(gòu)Linux

2023-06-30 08:27:20

2017-11-15 08:50:59

數(shù)據(jù)庫(kù)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編程語(yǔ)言工具

2023-05-09 07:51:28

Spring循環(huán)依賴

2023-10-26 08:38:43

SQL排名平分分區(qū)

2022-02-22 10:50:19

IDEAGit工具,

2022-10-08 00:00:05

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

2017-01-22 15:09:08

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

2023-04-26 07:30:00

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

2022-03-31 18:59:43

數(shù)據(jù)庫(kù)InnoDBMySQL

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2021-08-27 07:06:09

DubboDocker技術(shù)
點(diǎn)贊
收藏

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