精品欧美一区二区三区在线观看 _久久久久国色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观看在线| zzijzzij亚洲日本少妇熟睡| 国产精品com| 男女羞羞免费视频| 精品国产一区二区三区噜噜噜| 成人久久18免费网站麻豆| 久久久久久尹人网香蕉| 波多野结衣av在线观看| 国内不卡的一区二区三区中文字幕| 亚洲一区二区视频在线观看| 视频一区三区| 人妻一区二区三区免费| 美腿丝袜亚洲综合| 久久免费精品视频| 欧美性生给视频| 亚州精品视频| 欧美xxxxxxxxx| 国产野外作爱视频播放| 搞黄网站在线看| 国产精品二区一区二区aⅴ污介绍| 国产乱码一区| 不卡的日韩av| 久久99国产精品久久99| 国产99久久精品一区二区 夜夜躁日日躁 | 99蜜桃在线观看免费视频网站| 在线观看免费av片| 欧美激情麻豆| 久久人人爽人人爽爽久久 | 国产精品传媒在线| 玛丽玛丽电影原版免费观看1977| www.成人在线观看| 久久99久国产精品黄毛片色诱| 日韩av成人在线观看| 日本一区二区三区免费视频| 欧美三级乱码| 麻豆乱码国产一区二区三区| 三级黄色片在线观看| 欧美限制电影| 国产香蕉精品视频一区二区三区| 日b视频在线观看| 国产精品videossex| 日韩欧美国产高清| www.久久com| 久久久国产精品入口麻豆| 欧美日韩一卡二卡| 天天爱天天操天天干| 另类专区亚洲| 色综合天天综合狠狠| 男人和女人啪啪网站| 2021中文字幕在线| 婷婷夜色潮精品综合在线| 日本中文字幕亚洲| 波多野结衣在线观看| 亚洲一区二区三区中文字幕 | 中国av在线播放| 亚洲另类一区二区| 精品久久久无码人妻字幂| 在线观看男女av免费网址| 尤物视频一区二区| 国产精品三级一区二区| 波多野结衣在线观看| 精品露脸国产偷人在视频| 99视频在线免费播放| 久久毛片亚洲| 精品1区2区3区| 天堂在线一区二区三区| 欧美高清hd| 亚洲成人网在线| 成人午夜剧场视频网站| 日韩精品网站| 色综合久久88| 国产精品一区二区三区四| 久久久久久夜| 成人在线一区二区| www.狠狠干| 91免费观看在线| 亚洲不卡一卡2卡三卡4卡5卡精品| 三级国产在线观看| 国产精品久久久久久久蜜臀| 欧美a级黄色大片| 美女网站在线看| 欧美日韩大陆在线| 国产女主播在线播放| 亚洲精华一区二区三区| 久久精品久久精品亚洲人| 久久精品久久国产| 日韩在线a电影| 91久久夜色精品国产网站| 欧美一区,二区| 日本一区二区三区国色天香 | 日韩和欧美一区二区三区| 91久久久精品| 午夜视频1000| 亚洲免费观看高清完整版在线观看| 999在线观看视频| 精品久久99| 日韩成人中文字幕在线观看| 影音先锋男人看片资源| 亚洲精品系列| 成人精品网站在线观看| av女名字大全列表| 亚洲欧美日韩中文播放| 国产黄色特级片| 91欧美极品| 中文字幕免费国产精品| 日韩精品视频播放| 精品无人码麻豆乱码1区2区| 免费在线观看一区二区| 国产黄色小视频在线| 日韩欧美在线免费观看| 潘金莲一级淫片aaaaa| 成人亚洲一区二区| 4438全国成人免费| 精品免费久久久| 国产精品久久久久影院老司| 动漫av网站免费观看| 日韩精品成人| 日韩中文字幕网址| 成人免费一级片| 91论坛在线播放| 国产freexxxx性播放麻豆| 在线观看欧美| 在线观看国产成人av片| 天天干天天干天天干天天| 成人午夜看片网址| 午夜探花在线观看| 久久亚洲国产精品尤物| 亚洲国产美女久久久久| 久久精品www人人爽人人| 国产一区激情在线| 一区二区不卡在线观看| 韩日精品一区| 中国china体内裑精亚洲片| 亚洲熟女综合色一区二区三区| www.爱久久.com| 国产96在线 | 亚洲| 777久久精品| 欧美精品电影免费在线观看| 精品国产999久久久免费| 亚洲三级在线观看| 91av视频免费观看| 亚洲成人av| 川上优av一区二区线观看| 日本高清在线观看wwwww色| 欧美日韩一区二区在线观看 | 日韩精品在线播放视频| 日产精品一区二区| 国产日韩欧美在线视频观看| 里番在线观看网站| 欧美绝品在线观看成人午夜影视| 免费精品在线视频| 国产中文一区二区三区| 91成人在线视频观看| 精品一区二区三区中文字幕在线 | 日韩精品亚洲视频| av资源免费观看| 久久久午夜精品理论片中文字幕| 日本熟妇人妻xxxxx| 日韩国产综合| 亚洲free性xxxx护士白浆| 丝袜在线观看| 亚洲国产小视频在线观看| 亚洲永久精品在线观看| 久久久久久99久久久精品网站| 天天操天天摸天天爽| 日韩中文在线电影| 51蜜桃传媒精品一区二区| 福利在线导航136| 亚洲人成电影网站色xx| 亚洲自拍偷拍另类| 一区二区视频在线看| 亚洲国产精品成人综合久久久| 日韩精品一级中文字幕精品视频免费观看 | 亚洲国产午夜精品| 亚洲视频综合| 欧美亚洲一级二级| 亚洲电影二区| 午夜精品一区二区三区在线播放 | 91禁在线观看| 亚洲一区二区成人在线观看| 日本aaa视频| 精品一区二区国语对白| 免费不卡av在线| 欧美理论在线播放| 国产99在线免费| 韩国三级一区| 欧美乱大交xxxxx另类电影| 天堂在线视频网站| 欧美日韩国产a| 日本在线观看中文字幕| 国产精品视频一二三区| 精品无码av一区二区三区| 免费观看成人av| 91成人在线观看喷潮教学| 久久麻豆精品| 久久久亚洲综合网站| 日韩一级特黄| 日本久久久久久久久久久| 蜜桃视频在线观看免费视频网站www| 精品国产青草久久久久福利| 中文字幕在线2018| 五月激情六月综合| 一级性生活免费视频| 91色视频在线| 国产chinese中国hdxxxx| 韩日精品视频一区| 日韩中文字幕免费在线| 激情综合激情| 91九色国产ts另类人妖| 欧美欧美黄在线二区| 国产视频在线观看一区| 成人污版视频| 国产自产女人91一区在线观看| 亚洲一区资源| 69久久夜色精品国产69| 2024最新电影在线免费观看| 中文字幕亚洲综合久久筱田步美 | 久久精品人人爽| av在线1区2区| 亚洲理论在线a中文字幕| 成人午夜福利视频| 51精品国自产在线| 伊人22222| 日本韩国精品在线| 国产尤物在线视频| 亚洲福利视频一区二区| 欧美日韩在线国产| 亚洲免费在线视频一区 二区| 特黄一区二区三区| 国产日韩精品一区二区浪潮av| 人妻无码一区二区三区| av一本久道久久综合久久鬼色| 能看毛片的网站| 国产精品主播直播| 亚洲高清在线不卡| 狠狠色综合播放一区二区| 日韩av片网站| 精品一区二区三区在线观看国产| 色婷婷狠狠18| 久久精品av麻豆的观看方式| 亚洲欧美自拍另类日韩| 美女网站色91| 国产aⅴ爽av久久久久| 精久久久久久久久久久| 亚洲美女性囗交| 国产一区免费电影| 在线观看一区二区三区视频| 国产裸体歌舞团一区二区| 精产国品一区二区三区| 粉嫩高潮美女一区二区三区 | 久久免费视频网站| av中文字幕在线观看第一页| 欧美一区二区三区四区在线| 亚洲www啪成人一区二区| 国产精品日韩在线| 国产一区二区在线观| 国产伦精品一区二区三毛| 人人精品亚洲| 手机在线观看国产精品| 偷拍欧美精品| 日韩精品在线视频免费观看| 欧美一级网站| 亚洲图色中文字幕| 成人午夜视频免费看| 91精品人妻一区二区三区蜜桃欧美| 国产亚洲欧美在线| 5566中文字幕| 亚洲国产精品久久不卡毛片| 无码人妻精品一区二| 欧美高清视频在线高清观看mv色露露十八 | 精品国产123| 久香视频在线观看| 日韩中文字幕在线| h片视频在线观看| 国产精品扒开腿做爽爽爽的视频| 日韩福利在线观看| 国产精品三区www17con| 亚洲精品国模| 经典三级在线视频| 欧美一级久久| 四虎国产精品免费| 久久久久免费观看| 日韩影院一区二区| 婷婷开心久久网| 国产毛片一区二区三区va在线| 亚洲福利视频在线| www.成人.com| 2019日本中文字幕| 亚洲一区二区av| 久久久久久久久一区二区| 亚洲九九视频| 992kp快乐看片永久免费网址| 国产精品主播直播| 精品欧美一区二区久久久| 亚洲精品成人在线| 欧美激情一区二区三区免费观看| 精品久久久久av影院| 1024视频在线| 2018国产精品视频| 91国内精品| 亚洲一二三区精品| 免费亚洲婷婷| a级一a一级在线观看| 亚洲美女屁股眼交3| 国产成人av免费| 精品一区二区三区四区在线| 性欧美高清come| 国产热re99久久6国产精品| 国产99久久| 少妇高潮喷水在线观看| 国产盗摄一区二区三区| 999精品久久久| 在线观看国产日韩| 外国精品视频在线观看 | av亚洲产国偷v产偷v自拍| 2021亚洲天堂| 欧美久久一区二区| 国模吧精品人体gogo| 91精品国产高清久久久久久91| 天堂va在线高清一区| 亚洲天堂av免费在线观看| 日本中文字幕一区二区有限公司| 不卡一区二区在线观看| 精品久久久久久久久久久久久 | 久久香蕉视频网站| 麻豆精品国产91久久久久久| 白丝女仆被免费网站| 五月婷婷色综合| 免费观看毛片网站| 欧美激情三级免费| 网站一区二区| 日韩中文字幕在线不卡| 国产在线不卡一区| 99热6这里只有精品| 精品视频一区三区九区| 888av在线| 成人激情视频网| 91超碰成人| wwwxxx色| 午夜久久久影院| 五十路在线视频| 欧美中文在线字幕| 亚洲永久精品唐人导航网址| 国产a级一级片| 久久久久久久久一| 中文字字幕在线中文乱码| 在线观看日韩av| 婷婷久久免费视频| 91精品一区二区三区四区| 国产成人精品亚洲日本在线桃色 | 欧美日韩黄色一区二区| 美女隐私在线观看| 147欧美人体大胆444| 国产精品99一区二区| xxxwww国产| 色综合色综合色综合色综合色综合 | a亚洲天堂av| 青青视频在线免费观看| 色爱av美腿丝袜综合粉嫩av| 国产精品中文| 国产极品尤物在线| 久久精品欧美一区二区三区麻豆| 亚洲视频一区在线播放| 欧美成人在线免费视频| 久草在线综合| 9久久婷婷国产综合精品性色 | 人人干人人干人人干| 亚洲男人天堂视频| 国产精品成人国产| 国产制服91一区二区三区制服| zzijzzij亚洲日本少妇熟睡| 国产第一页在线观看| 久久午夜a级毛片| 欧美成人专区| 亚欧激情乱码久久久久久久久| 一区二区三区在线免费观看 | 久久嫩草精品久久久精品| 中文字幕视频免费观看| 欧美精品在线看| 亚洲精华一区二区三区| 亚洲精品视频三区| 五月婷婷激情综合| 午夜伦理在线| 精品免费国产| 精品一区二区日韩| 亚洲另类欧美日韩| 久久亚洲影音av资源网| 日韩精品免费一区二区三区竹菊| 亚洲少妇久久久| 同产精品九九九| 69xxx在线| 青青草成人激情在线| 福利一区二区在线| 中文字幕无码乱码人妻日韩精品| 欧美激情亚洲一区| 久久在线视频|