【spring AOP】AspectJProxyFactory
AspectJProxyFactory,可能大家對這個比較陌生,但是@Aspect這個註解大家應該很熟悉吧,通過這個註解在spring環境中實現aop特別的方便。
而AspectJProxyFactory這個類可以通過解析@Aspect標註的類來生成代理aop代理物件,對開發者來說,使建立代理變的更簡潔了。
先了解幾個概念
文中會涉及幾個概念,先了解一下。
target
用來表示目標物件,即需要通過aop來增強的物件。
proxy
代理物件,target通過aop增強之後生成的代理物件。
AspectJ是什麼?
AspectJ是一個面向切面的框架,是目前最好用,最方便的AOP框架,和spring中的aop可以整合在一起使用,通過Aspectj提供的一些功能實現aop代理變得非常方便。
AspectJ使用步驟
1.建立一個類,使用@Aspect標註
2.@Aspect標註的類中,通過@Pointcut定義切入點
3.@Aspect標註的類中,通過AspectJ提供的一些通知相關的註解定義通知
4.使用AspectJProxyFactory結合@Ascpect標註的類,來生成代理物件
案例
來個類
package com.javacode2018.aop.demo9.test1; public class Service1 { public void m1() { System.out.println("我是 m1 方法"); } public void m2() { System.out.println(10 / 0); System.out.println("我是 m2 方法"); } }
通過AspectJ來對Service1進行增強,來2個通知,一個前置通知,一個異常通知,這2個通知需要對Service1中的所有方法生效,實現如下:
package com.javacode2018.aop.demo9.test1; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; //@1:這個類需要使用@Aspect進行標註 @Aspect public class Aspect1 { //@2:定義了一個切入點,可以匹配Service1中所有方法 @Pointcut("execution(* com.javacode2018.aop.demo9.test1.Service1.*(..))") public void pointcut1() { } //@3:定義了一個前置通知,這個通知對剛剛上面我們定義的切入點中的所有方法有效 @Before(value = "pointcut1()") public void before(JoinPoint joinPoint) { //輸出連線點的資訊 System.out.println("前置通知," + joinPoint); } //@4:定義了一個異常通知,這個通知對剛剛上面我們定義的切入點中的所有方法有效 @AfterThrowing(value = "pointcut1()", throwing = "e") public void afterThrowing(JoinPoint joinPoint, Exception e) { //發生異常之後輸出異常資訊 System.out.println(joinPoint + ",發生異常:" + e.getMessage()); } }
@1:類上使用@Aspect標註
@2:通過@Pointcut註解標註在方法上面,用來定義切入點
@3:使用@Before標註在方法上面,定義了一個前置通知,通過value引用了上面已經定義的切入點,表示這個通知會對Service1中的所有方法生效,在通知中可以通過這個類名.方法名()引用@Pointcut定義的切入點,表示這個通知對這些切入點有效,若@Before和@Pointcut在一個類的時候,直接通過方法名()引用當前類中定義的切入點
@4:這個使用@AfterThrowing定義了一個異常通知,也是對通過value引用了上面已經定義的切入點,表示這個通知會對Service1中的所有方法生效,若Service1中的方法丟擲了Exception型別的異常,都會回撥afterThrowing方法。
來個測試類
package com.javacode2018.aop.demo9;
import com.javacode2018.aop.demo9.test1.Aspect1;
import com.javacode2018.aop.demo9.test1.Service1;
import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
public class AopTest9 {
@Test
public void test1() {
try {
//對應目標物件
Service1 target = new Service1();
//建立AspectJProxyFactory物件
AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
//設定被代理的目標物件
proxyFactory.setTarget(target);
//設定標註了@Aspect註解的類
proxyFactory.addAspect(Aspect1.class);
//生成代理物件
Service1 proxy = proxyFactory.getProxy();
//使用代理物件
proxy.m1();
proxy.m2();
} catch (Exception e) {
}
}
}
執行輸出
前置通知,execution(void com.javacode2018.aop.demo9.test1.Service1.m1())
我是 m1 方法
前置通知,execution(void com.javacode2018.aop.demo9.test1.Service1.m2())
execution(void com.javacode2018.aop.demo9.test1.Service1.m2()),發生異常:/ by zero
AspectJProxyFactory原理
@Aspect
標註的類上,這個類中,可以通過通過@Pointcut
來定義切入點,可以通過@Before
、@Around
、@After
、@AfterRunning
、@AfterThrowing
標註在方法上來定義通知,定義好了之後,將@Aspect
標註的這個類交給AspectJProxyFactory
來解析生成Advisor鏈,進而結合目標物件一起來生成代理物件,大家可以去看一下原始碼,比較簡單,這裡就不多解釋了。