Spring 面向切面編程AOP實(shí)現(xiàn)詳解
簡(jiǎn)介
1、什么叫做面向切面編程?
概念:把一個(gè)個(gè)的橫切關(guān)注點(diǎn)(某種業(yè)務(wù)的實(shí)現(xiàn)代碼)放到某個(gè)模塊中去,稱之為切面。每個(gè)切面影響業(yè)務(wù)的一種功能,切面的目的就是為了功能增強(qiáng),將需要增強(qiáng)的方法做成切面,實(shí)現(xiàn)對(duì)業(yè)務(wù)的增強(qiáng),就是面向切面編程。
目的:將與業(yè)務(wù)本身無(wú)關(guān),卻被業(yè)務(wù)模塊所共同調(diào)用的功能代碼封裝成切面,以減少系統(tǒng)的重復(fù)代碼,降低耦合,提高可擴(kuò)展性。
優(yōu)勢(shì):把多個(gè)方法前/后的共同代碼抽離出來(lái),使用動(dòng)態(tài)代理機(jī)制來(lái)控制,先執(zhí)行抽離出來(lái)的代碼,再執(zhí)行每一個(gè)真實(shí)方法.
2、Spring中的AOP使用動(dòng)態(tài)代理來(lái)實(shí)現(xiàn):
- 如果一個(gè)類實(shí)現(xiàn)了接口,那么spring就使用JDK的動(dòng)態(tài)代理完成AOP;
- 如果一個(gè)類沒(méi)有實(shí)現(xiàn)接口,那么spring就是用cglib完成AOP。
3、AOP的一些基本概念
- Joinpoint:連接點(diǎn),被攔截到需要被增強(qiáng)的方法。去哪里做增強(qiáng)
- Pointcut:切入點(diǎn),哪些包中的哪些類中的哪些方法,可認(rèn)為是連接點(diǎn)的集合。去哪些地方做增強(qiáng)
- Advice:增強(qiáng),當(dāng)攔截到Joinpoint之后,在方法執(zhí)行的什么時(shí)機(jī)(when)做什么樣(what)的增強(qiáng)。
- Aspect:切面,Pointcut+Advice,去哪些地方+在什么時(shí)候+做什么增強(qiáng)
- Weaving:織入,把Advice加到Target上之后,創(chuàng)建出Proxy對(duì)象的過(guò)程。
切入點(diǎn)語(yǔ)法
1、execution(<訪問(wèn)修飾符>?<返回值類型><聲明類型>?<方法名>(<參數(shù)名>)<異常名>)
?表示出現(xiàn)0次或1次
通配符:
* :匹配任何部分,只能表示一個(gè)單詞
.. : 可用于全限定名中和方法參數(shù)中,分別表示子包和0到N個(gè)參數(shù)
2、實(shí)例介紹:
XML方式實(shí)現(xiàn)AOP
1、導(dǎo)入依賴
spring-aop spring-aspectj
2、命名空間
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "></beans>
3、配置AOP
<!--配置AOP--> <aop:config> <!--配置切入點(diǎn)pointcut 哪些包里的哪些類需要被增強(qiáng) --> <aop:pointcut id="pointcut" expression="execution( * com.test.class03_AOP_xml.service.IUserService.*(..))"/> <!--配置切面Aspect Aspect=pointcut+Advice --> <aop:aspect ref="txManager"> <!--前置增強(qiáng)--> <aop:before method="begin" pointcut-ref="pointcut"/> <!--后置增強(qiáng)--> <aop:after-returning method="commit" pointcut-ref="pointcut"/> <!--異常增強(qiáng)--> <aop:after-throwing method="rollback" pointcut-ref="pointcut"/> <!--最終增強(qiáng)--> <aop:after method="destroy" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
4、AOP中幾個(gè)不同的增強(qiáng)時(shí)機(jī):
- aop:before(前置增強(qiáng)):在方法執(zhí)行之前執(zhí)行增強(qiáng);
- aop:after-returning(后置增強(qiáng)):在方法正常執(zhí)行完成之后執(zhí)行增強(qiáng);
- aop:after-throwing(異常增強(qiáng)):在方法拋出異常退出時(shí)執(zhí)行增強(qiáng);
- aop:after(最終增強(qiáng)):在方法執(zhí)行之后執(zhí)行,相當(dāng)于在finally里面執(zhí)行;可以通過(guò)配置throwing來(lái)獲得攔截到的異常信息
- aop:around(環(huán)繞增強(qiáng)):最強(qiáng)大的一種增強(qiáng)類型。
環(huán)繞增強(qiáng)可以在方法調(diào)用前后完成自定義的行為,環(huán)繞增強(qiáng)有兩個(gè)要求
1、方法要返回一個(gè)Object(返回的結(jié)果)
2、方法的第一個(gè)參數(shù)是ProceedingJoinPoint(可以繼續(xù)向下傳遞的切入點(diǎn))
<!--環(huán)繞增強(qiáng)--> <aop:around method="around" pointcut-ref="pointcut"/>
5、代碼示例
public class TxManager { public void begin() { System.out.println("開啟事務(wù)###"); } public void commit() { System.out.println("提交事務(wù)++++++"); } public void rollback() { System.out.println("回滾事務(wù)...."); } public void destroy() { System.out.println("釋放資源……………………"); } //環(huán)繞增強(qiáng)代碼示例 public Object around(ProceedingJoinPoint pjp){ Object obj=null; try { System.out.println("開啟事務(wù)###"); obj=pjp.proceed(); System.out.println("提交事務(wù)++++++"); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println("回滾事務(wù)...."); }finally { System.out.println("釋放資源……………………"); } return obj; } }
6、獲取增強(qiáng)的參數(shù)
1.在增強(qiáng)方法中獲取異常的信息。
<aop:after-throwing>的標(biāo)簽中添加throwing=“ex”的屬性
增強(qiáng)方法rollback中,添加形式參數(shù):Exception ex。
則形參ex中就自動(dòng)注入了異常對(duì)象。 注意:throwing屬性的值,必須與方法中形參的名字相同
2.在增強(qiáng)方法中,獲取被增強(qiáng)方法的信息
Spring AOP提供org.aspectj.lang.JoinPoint類作為增強(qiáng)方法的第一個(gè)參數(shù)。
JoinPoint :提供訪問(wèn)當(dāng)前被增強(qiáng)方法的真實(shí)對(duì)象、代理對(duì)象、方法參數(shù)等數(shù)據(jù)。
ProceedingJoinPoint:JinPoint子類,只用于環(huán)繞增強(qiáng)中,可以處理被增強(qiáng)方法。
- jp.getThis():獲取代理對(duì)象
- jp.getTarget():獲取目標(biāo)對(duì)象
- jp.getArgs():獲取被增強(qiáng)方法的參數(shù)
- jp.getSignature():獲取被增強(qiáng)方法的參數(shù)
注解方式實(shí)現(xiàn)AOP
1、命名空間
2、添加注解解析器<aop:aspect-autoproxy/>
3、@Aspect 切面,下面的注解都在切面里配置
- @before
- @AfterReturning
- @AfterThrowing
- @After
- @Around
4、代碼示例
@Aspect public class TxManager { @Pointcut("execution( * com.test.class04_AOP_Anno.service.IUserService.*(..))") public void tt(){} @Before("tt()") public void begin() { System.out.println("開啟事務(wù)###"); } @AfterReturning("tt()") public void commit() { System.out.println("提交事務(wù)++++++"); } @AfterThrowing(value="tt()",throwing = "ex") public void rollback() { System.out.println("回滾事務(wù)...."); } @After("tt()") public void destroy() { System.out.println("釋放資源……………………"); } @Around("tt()") public Object around(ProceedingJoinPoint pjp){ Object obj=null; try { System.out.println("開啟事務(wù)###"); obj=pjp.proceed(); System.out.println("提交事務(wù)++++++"); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println("回滾事務(wù)...."); }finally { System.out.println("釋放資源……………………"); } return obj; } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)的獲取和判斷文件頭信息工具類用法示例
這篇文章主要介紹了Java實(shí)現(xiàn)的獲取和判斷文件頭信息工具類,結(jié)合實(shí)例形式分析了Java針對(duì)文件讀取及頭信息判斷相關(guān)操作技巧,需要的朋友可以參考下2017-11-11Mybatis中兼容多數(shù)據(jù)源的databaseId(databaseIdProvider)的簡(jiǎn)單使用方法
本文主要介紹了Mybatis中兼容多數(shù)據(jù)源的databaseId(databaseIdProvider)的簡(jiǎn)單使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07關(guān)于log4j日志擴(kuò)展---自定義PatternLayout
這篇文章主要介紹了關(guān)于log4j日志擴(kuò)展---自定義PatternLayout,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12springboot時(shí)間格式化的五種方法總結(jié)(解決后端傳給前端的時(shí)間顯示不一致)
這篇文章主要給大家介紹了關(guān)于springboot時(shí)間格式化的五種方法,文中介紹的方法解決了后端傳給前端的時(shí)間顯示不一致,文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01Java并發(fā)線程之線程池的知識(shí)總結(jié)
這篇文章主要介紹了Java并發(fā)線程之線程池的知識(shí)總結(jié),幫助大家更好的理解和學(xué)習(xí)Java并發(fā)線程的相關(guān)內(nèi)容,感興趣的朋友可以了解下2021-01-01@ConfigurationProperties加載外部配置方式
這篇文章主要介紹了@ConfigurationProperties加載外部配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03springMvc請(qǐng)求的跳轉(zhuǎn)和傳值的方法
本篇文章主要介紹了springMvc請(qǐng)求的跳轉(zhuǎn)和傳值的方法,這里整理了幾種跳轉(zhuǎn)方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02