spring的AOP配置之@注解方式
AOP配置(注解)
spring的AOP概念在spring的AOP配置之XML方式這騙博客中詳細(xì)介紹了,這篇博客就直接開始介紹AOP配置需要那些注解
AOP注解詳解
@Aspect 標(biāo)志為一個切面類
? 名稱:@Aspect
? 類型:注解
? 位置:類定義上方
? 作用:設(shè)置當(dāng)前類為切面類
? 格式:
? 說明:一個beans標(biāo)簽中可以配置多個aop:config標(biāo)簽
@Pointcut 使用當(dāng)前方法名作為切入點引用名稱
? 名稱:@Pointcut
? 類型:注解
? 位置:方法定義上方
? 作用:使用當(dāng)前方法名作為切入點引用名稱
? 格式:
? 說明:被修飾的方法忽略其業(yè)務(wù)功能,格式設(shè)定為無參無返回值的方法,方法體內(nèi)空實現(xiàn)(非抽象)
@Before 標(biāo)注當(dāng)前方法作為前置通知
? 名稱:@Before
? 類型:注解
? 位置:方法定義上方
? 作用:標(biāo)注當(dāng)前方法作為前置通知
? 格式:
? 特殊參數(shù):
◆ 無
@After 標(biāo)注當(dāng)前方法作為后置通知
名稱:@After
? 類型:注解
? 位置:方法定義上方
? 作用:標(biāo)注當(dāng)前方法作為后置通知
? 格式:
? 特殊參數(shù):
◆ 無
@AfterReturning 標(biāo)注當(dāng)前方法執(zhí)行成功后作為返回后通知
? 名稱:@AfterReturning
? 類型:注解
? 位置:方法定義上方
? 作用:標(biāo)注當(dāng)前方法作為返回后通知
? 格式:
? 特殊參數(shù):
◆ returning :設(shè)定使用通知方法參數(shù)接收返回值的變量名
@AfterThrowing 標(biāo)注當(dāng)前方法作為異常后通知
? 名稱:@AfterThrowing
? 類型:注解
? 位置:方法定義上方
? 作用:標(biāo)注當(dāng)前方法作為異常后通知
? 格式:
? 特殊參數(shù):
◆ throwing :設(shè)定使用通知方法參數(shù)接收原始方法中拋出的異常對象名
@Around 標(biāo)注當(dāng)前方法作為環(huán)繞通知
AOP注解詳解
? 名稱:@Around
? 類型:注解
? 位置:方法定義上方
? 作用:標(biāo)注當(dāng)前方法作為環(huán)繞通知
? 格式:
? 特殊參數(shù):
◆ 無
@EnableAspectJAutoProxy AOP注解驅(qū)動
? 名稱:@EnableAspectJAutoProxy
? 類型:注解
? 位置:Spring注解配置類定義上方
? 作用:設(shè)置當(dāng)前類開啟AOP注解驅(qū)動的支持,加載AOP注解
? 格式:
注解開發(fā)AOP注意事項
AOP注解代碼實現(xiàn)
圖解AOP從xml轉(zhuǎn)變?yōu)閄ML
POM
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.9.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.1.9.RELEASE</version></dependency><!-- aop切面包--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency><!-- junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies>SpringConfig配置類
package com.fs.config;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; //標(biāo)志為配置類 @Configuration //掃描那些路徑下的包的類的spring注解 @ComponentScan("com.fs") //開啟AOP注解支持 替換 xml <aop:aspectj-autoproxy/> @EnableAspectJAutoProxy public class SpringConfig { }模擬三層架構(gòu)的server,動態(tài)代理service接口的實現(xiàn)類
AopService接口
package com.fs.service;public interface AopService {void findAll();int add(String str);void findById();void del();void update(); }AopServiceImpl實現(xiàn)類
package com.fs.service.impl;import com.fs.service.AopService; import org.springframework.stereotype.Service;//把業(yè)務(wù)類交給spring管理 @Service public class AopServiceImpl implements AopService {@Overridepublic void findAll() {System.out.println("業(yè)務(wù)層執(zhí)行了findAll~~~");}/**** @param str 傳遞一個參數(shù),在切面類的通知方法中去接收查看* @return 返回一個值,在切面類的通知方法中去接收*/@Overridepublic int add(String str) {System.out.println("業(yè)務(wù)層執(zhí)行了add~~~");//返回一個值,在切面類的通知方法中去接收return 54088;}@Overridepublic void findById() {System.out.println("業(yè)務(wù)層執(zhí)行了findById~~~");//制造異常來是異常通知生效 // int i = 1/0;}@Overridepublic void del() {System.out.println("業(yè)務(wù)層執(zhí)行了del~~~");}@Overridepublic void update() {System.out.println("業(yè)務(wù)層執(zhí)行了update~~~");} }@Aspect 切面類
package com.fs.aop;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component;import java.util.Arrays;/* 這個類是AOP的切面類里面編輯一些織入的方法*///將這個類交給spring管理 @Component //標(biāo)志這個類為切面類 @Aspect public class AOPDemoAdvice {//配置切入點,切入這個com.fs.service.AopService.find*(..)方法,因為ioc中存入了實現(xiàn)類,執(zhí)行切方法的時候會從ioc中獲取實現(xiàn)類@Pointcut("execution(* com.fs.service.AopService.find*(..))")public void pt(){}// @Before("pt()")public void proxyAOPBefore(JoinPoint jp){Object[] args = jp.getArgs();System.out.println("給切入點(方法)添加了前置通知~~~"+".."+ Arrays.toString(args)+"...");}// @After("pt()")public void proxyAOPAfter(){/*這個后置通知是無論代碼是否出現(xiàn)異常,都會執(zhí)行這個通知*/System.out.println("給切入點(方法)添加了后置通知~~~");}//測試獲取切入點的的參數(shù)和返回值//這個注解,可以獲取方法正常執(zhí)行后,獲取方法的返回值 returning是返回值的名字,自己定義名字 // @AfterReturning(value = "execution(* com.fs.service.impl.*.add(..))",returning = "num")//直接切入點位接口的方法也行.因為我們在ioc中有存入了實現(xiàn)類的@AfterReturning(value = "execution(* com.fs.service.AopService.add(..))",returning = "num")public void proxyAOPAfterReturning(JoinPoint jp,Object num) {/*BeforeReturning表示的是代碼運行成功無任何異常,會執(zhí)行的通知*///獲取傳遞的參數(shù)Object[] args = jp.getArgs();System.out.println("給切入點(方法)添加了代碼運行成功后的后置通知~~~"+".切入點傳遞的參數(shù)."+Arrays.toString(args)+".切入點返回的值."+num);}// @AfterThrowing("pt()")public void proxyAOPAfterThrowing() {System.out.println("給切入點(方法)添加了代碼運行異常后的后置通知~~~");}/*環(huán)繞通知環(huán)繞通知可以將上面的通知方法全部實現(xiàn)ProceedingJoinPoint這類就代表切入點,可以給這個切入點執(zhí)行配置通知*/@Around("pt()") // @Around("execution(* com.fs.service.impl.*.find*(..))")也可以在后面直接寫切入點的表達(dá)式public Object proxyAOPAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {Object proceed = null;try {//proceedingJoinPoint切入點執(zhí)行前配置前置通知System.out.println("環(huán)繞通知的前置通知執(zhí)行的代碼");//切入點(被動態(tài)代理的方法)執(zhí)行proceed = proceedingJoinPoint.proceed();//proceedingJoinPoint切入點執(zhí)行成功無報錯后配置前置通知System.out.println("環(huán)繞通知的-成功運行-后執(zhí)行的代碼");} catch (Throwable throwable) {//proceedingJoinPoint切入點執(zhí)行前配置異常通知System.out.println("環(huán)繞通知的切入點執(zhí)行-異常后-執(zhí)行的代碼");throwable.printStackTrace();} finally {//proceedingJoinPoint切入點執(zhí)行前后通知,就是代碼無論是異常,還成功運行,都會執(zhí)行的增強代碼System.out.println("環(huán)繞通知的后置通知執(zhí)行的代碼");}return proceed;} }測試類
package com.fs.aop;import com.fs.config.SpringConfig; import com.fs.service.AopService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import static org.junit.Assert.*; //開啟junit的執(zhí)行器 @RunWith(SpringJUnit4ClassRunner.class) //加載spring的配置類 @ContextConfiguration(classes = SpringConfig.class) public class AopDemoTest {//從ioc中獲取@Autowiredprivate AopService aopService;@Testpublic void method() {//調(diào)用方法aopService.findById();// int add = aopService.add("牛批");}}aopService.findById();執(zhí)行結(jié)果
aopService.add(“牛批”);執(zhí)行結(jié)果
AOP注解開發(fā)通知執(zhí)行順序控制(了解)
? AOP使用XML配置情況下,通知的執(zhí)行順序由配置順序決定,在注解情況下由于不存在配置順序的概念
的概念,參照通知所配置的方法名字符串對應(yīng)的編碼值順序,可以簡單理解為字母排序
◆ 同一個通知類中,相同通知類型以方法名排序為準(zhǔn)
◆ 不同通知類中,以類名排序為準(zhǔn)
◆ 使用@Order注解通過變更bean的加載順序改變通知的加載順序
? 企業(yè)開發(fā)經(jīng)驗
◆ 通知方法名由3部分組成,分別是前綴、順序編碼、功能描述
◆ 前綴為固定字符串,例如baidu、itheima等,無實際意義
◆ 順序編碼為6位以內(nèi)的整數(shù),通常3位即可,不足位補0
◆ 功能描述為該方法對應(yīng)的實際通知功能,例如exception、strLenCheck
◆ 控制通知執(zhí)行順序使用順序編碼控制,使用時做一定空間預(yù)留
? 003使用,006使用,預(yù)留001、002、004、005、007、008
? 使用時從中段開始使用,方便后期做前置追加或后置追加
? 最終順序以運行順序為準(zhǔn),以測試結(jié)果為準(zhǔn),不以設(shè)定規(guī)則為準(zhǔn)
總結(jié)
以上是生活随笔為你收集整理的spring的AOP配置之@注解方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring的AOP配置之XML方式
- 下一篇: spring中AOP动态代理的两种方式