SpringAOP 構(gòu)造注入的實(shí)現(xiàn)步驟
AOP_面向切面編程初步了解
讓我們先想象一個(gè)場景,你正在編寫一個(gè)項(xiàng)目,在開發(fā)過程中的多個(gè)模塊都有某段重復(fù)的代碼,于是你選擇將其抽象成一個(gè)方法,然后在需要的地方調(diào)用這個(gè)方法,當(dāng)需要修改這段代碼時(shí)只需要修改這個(gè)方法就行。有一天,你的Boss給了新的需求,需要再抽象出一個(gè)方法,然后再在各個(gè)需要這個(gè)方法的模塊調(diào)用這個(gè)方法,這可能就讓你頭疼了,需要修改大量的代碼,于是會想,能不能不修改源代碼為系統(tǒng)業(yè)務(wù)添加某種功能呢?幸運(yùn)的是,AOP可以很好的解決這個(gè)問題。
簡單介紹
AOP:保證開發(fā)者不修改源代碼的前提下,去為系統(tǒng)中的業(yè)務(wù)組件添加某種通用功能,本質(zhì)是由AOP框架修改業(yè)務(wù)組件的多個(gè)方法的源代碼,我們將其分為兩類:
- 靜態(tài)AOP
AOP 框架在編譯階段對程序源代碼進(jìn)行修改,生成了靜態(tài)的 AOP 代理類(生成的*.class文件已經(jīng)被改掉了,需要使用特定的編譯器),比如 AspectJ。
- 動(dòng)態(tài)AOP:
AOP 框架在運(yùn)行階段對動(dòng)態(tài)生成代理對象(在內(nèi)存中以 JDK 動(dòng)態(tài)代理,或 CGlib 動(dòng)態(tài)地生成 AOP 代理類),如 SpringAOP。
詳細(xì)說明
Spring 的通知類型
名稱 | 標(biāo)簽 | 說明 |
---|---|---|
前置通知 | @Before | 用于配置前置通知。指定增強(qiáng)的方法在切入點(diǎn)方法之前執(zhí)行 |
后置通知 | @AfterReturning | 用于配置后置通知。指定增強(qiáng)的方法在切入點(diǎn)方法之后執(zhí)行 |
環(huán)繞通知 | @Around | 用于配置環(huán)繞通知。指定增強(qiáng)的方法在切入點(diǎn)方法之前和之后都執(zhí)行 |
異常通知 | @AfterThrowing | 用于配置異常拋出通知。指定增強(qiáng)的方法在出現(xiàn)異常時(shí)執(zhí)行 |
最終通知 | @After | 用于配置最終通知。無論增強(qiáng)方式執(zhí)行是否有異常都會執(zhí)行 |
切面類注解 | @Aspect | 標(biāo)注該當(dāng)前類是一個(gè)切面類 |
斷點(diǎn)注解 | @Pointcut | 使用一個(gè)返回值為 void 、方法體為空的方法來命名切入點(diǎn) |
實(shí)戰(zhàn)演練
導(dǎo)入依賴包
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.3.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency> <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance --> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
創(chuàng)建一個(gè)增強(qiáng)類以及其接口
增強(qiáng)類接口:
public interface VisitService { //用于實(shí)現(xiàn)前置通知,后置通知,異常通知,最終通知 void visit(String str) throws Exception; //用于實(shí)現(xiàn)環(huán)繞通知 void around(); }
增強(qiáng)類:
public class VisitServiceImpl implements VisitService { //前置,后置,最終,異常通知的增強(qiáng)類 public void visit(String str) throws Exception{ System.out.println(str); if(!str.equalsIgnoreCase("agree")){ throw new Exception("非法訪問"); } } //環(huán)繞通知的增強(qiáng)類 public void around() { System.out.println("環(huán)繞通知"); } }
創(chuàng)建一個(gè)切面類
@Component("VisitAspect") @Aspect //標(biāo)注當(dāng)前myAspect是一個(gè)切面類 public class VisitAspect_anno { // 定義切入點(diǎn)表達(dá)式 // 使用一個(gè)返回值為 void 、方法體為空的方法來命名切入點(diǎn) @Pointcut("execution(* Spring_AOP.service.impl.VisitServiceImpl.visit(..))") private void v1() { } //前置通知 @Before("v1()") public void visitBefore(JoinPoint joinPoint) { System.out.println("口令:"); } @After("v1()") //最終通知,無論是否報(bào)錯(cuò),都執(zhí)行 public void visitAfter(JoinPoint joinPoint) { System.out.println("輸入完成"); } @AfterReturning("v1()") //后置通知報(bào)錯(cuò)不執(zhí)行 public void visitSuccess(JoinPoint joinPoint) { System.out.println("請求成功,歡迎"); } @AfterThrowing(value = "v1()",throwing = "ex") //異常通知,報(bào)錯(cuò)后執(zhí)行 public void visitThrow(JoinPoint joinPoint, Throwable ex) { System.out.println("請求失敗,拒絕"); } @Around("execution(* Spring_AOP.service.impl.VisitServiceImpl.around())") //環(huán)繞通知,如果報(bào)錯(cuò)只執(zhí)行前一句 public Object visitAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("-------環(huán)繞-------"); Object obj = proceedingJoinPoint.proceed(); System.out.println("------------------"); return obj; } }
配置xml文件
<!-- 基于注解的聲明式 AspectJ --> <context:component-scan base-package="Spring_AOP" /> <!-- 啟動(dòng)基于注解的聲明式 AspectJ 支持一 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
創(chuàng)建一個(gè)測試類
public class visitTest { @Test public void VisitTest(){ ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext_AOP.xml"); VisitService visitService = app.getBean(VisitService.class); try { visitService.visit("agree"); } catch (Exception e) { e.printStackTrace(); } try { visitService.visit("ok"); } catch (Exception e) { e.printStackTrace(); } visitService.around(); } }
測試運(yùn)行
口令:
agree
請求成功,歡迎
輸入完成
口令:
ok
請求失敗,拒絕
輸入完成
-------環(huán)繞-------
環(huán)繞通知
-------環(huán)繞-------
總結(jié)
使用構(gòu)造注入可以更方便的實(shí)現(xiàn)AOP模式,但是同樣與設(shè)置注入相比各有千秋。
以上就是以注解實(shí)現(xiàn)SpringAOP框架構(gòu)造注入的實(shí)現(xiàn),如有錯(cuò)誤,麻煩指出,感謝耐心到現(xiàn)在的朋友ᕕ( ᐛ )ᕗ
到此這篇關(guān)于SpringAOP_構(gòu)造注入的實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)SpringAOP_構(gòu)造注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)devtools實(shí)現(xiàn)熱部署過程解析
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)devtools實(shí)現(xiàn)熱部署過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03解析Java線程編程中的線程安全與synchronized的使用
這篇文章主要介紹了Java線程編程中的線程安全與synchronized的使用,synchronized多線程使用時(shí)一定要注意線程之間的沖突問題,需要的朋友可以參考下2015-12-12Spring循環(huán)依賴實(shí)現(xiàn)過程揭秘
這篇文章主要介紹了Spring循環(huán)依賴實(shí)現(xiàn)過程,Spring的解決循環(huán)依賴是有前置條件的,要解決循環(huán)依賴我們首先要了解Spring Bean對象的創(chuàng)建過程和依賴注入的方式2023-01-01詳解SpringCloudGateway內(nèi)存泄漏問題
這篇文章主要介紹了詳解SpringCloudGateway內(nèi)存泄漏問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07解決java字符串轉(zhuǎn)換成時(shí)間Unparseable date出錯(cuò)的問題
這篇文章主要介紹了解決java字符串轉(zhuǎn)換成時(shí)間Unparseable date出錯(cuò)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Spring Boot配置線程池拒絕策略的場景分析(妥善處理好溢出的任務(wù))
本文通過實(shí)例代碼給大家介紹下如何為線程池配置拒絕策略、如何自定義拒絕策略。對Spring Boot配置線程池拒絕策略的相關(guān)知識感興趣的朋友一起看看吧2021-09-09