AspectJProxyFactory,可能大家对这个比较陌生,但是@Aspect这个注解大家应该很熟悉吧,通过这个注解在spring环境中实现aop特别的方便。

AspectJProxyFactory这个类可以通过解析@Aspect标注的类来生成代理aop代理对象,对开发者来说,使创建代理变的更简洁了。

先了解几个概念

文中会涉及几个概念,先了解一下。

  1. target

用来表示目标对象,即需要通过aop来增强的对象。

  1. proxy

代理对象,target通过aop增强之后生成的代理对象。

AspectJ是什么?

AspectJ是一个面向切面的框架,是目前最好用,最方便的AOP框架,和spring中的aop可以集成在一起使用,通过Aspectj提供的一些功能实现aop代理变得非常方便。

AspectJ使用步骤

1.创建一个类,使用@Aspect标注

2.@Aspect标注的类中,通过@Pointcut定义切入点

3.@Aspect标注的类中,通过AspectJ提供的一些通知相关的注解定义通知

4.使用AspectJProxyFactory结合@Ascpect标注的类,来生成代理对象

案例

来个类

  1. package com.javacode2018.aop.demo9.test1;
  2. public class Service1 {
  3. public void m1() {
  4. System.out.println("我是 m1 方法");
  5. }
  6. public void m2() {
  7. System.out.println(10 / 0);
  8. System.out.println("我是 m2 方法");
  9. }
  10. }

通过AspectJ来对Service1进行增强,来2个通知,一个前置通知,一个异常通知,这2个通知需要对Service1中的所有方法生效,实现如下:

  1. package com.javacode2018.aop.demo9.test1;
  2. import org.aspectj.lang.JoinPoint;
  3. import org.aspectj.lang.annotation.AfterThrowing;
  4. import org.aspectj.lang.annotation.Aspect;
  5. import org.aspectj.lang.annotation.Before;
  6. import org.aspectj.lang.annotation.Pointcut;
  7. //@1:这个类需要使用@Aspect进行标注
  8. @Aspect
  9. public class Aspect1 {
  10. //@2:定义了一个切入点,可以匹配Service1中所有方法
  11. @Pointcut("execution(* com.javacode2018.aop.demo9.test1.Service1.*(..))")
  12. public void pointcut1() {
  13. }
  14. //@3:定义了一个前置通知,这个通知对刚刚上面我们定义的切入点中的所有方法有效
  15. @Before(value = "pointcut1()")
  16. public void before(JoinPoint joinPoint) {
  17. //输出连接点的信息
  18. System.out.println("前置通知," + joinPoint);
  19. }
  20. //@4:定义了一个异常通知,这个通知对刚刚上面我们定义的切入点中的所有方法有效
  21. @AfterThrowing(value = "pointcut1()", throwing = "e")
  22. public void afterThrowing(JoinPoint joinPoint, Exception e) {
  23. //发生异常之后输出异常信息
  24. System.out.println(joinPoint + ",发生异常:" + e.getMessage());
  25. }
  26. }

@1:类上使用@Aspect标注

@2:通过@Pointcut注解标注在方法上面,用来定义切入点

@3:使用@Before标注在方法上面,定义了一个前置通知,通过value引用了上面已经定义的切入点,表示这个通知会对Service1中的所有方法生效,在通知中可以通过这个类名.方法名()引用@Pointcut定义的切入点,表示这个通知对这些切入点有效,若@Before@Pointcut在一个类的时候,直接通过方法名()引用当前类中定义的切入点

@4:这个使用@AfterThrowing定义了一个异常通知,也是对通过value引用了上面已经定义的切入点,表示这个通知会对Service1中的所有方法生效,若Service1中的方法抛出了Exception类型的异常,都会回调afterThrowing方法。

来个测试类

  1. package com.javacode2018.aop.demo9;
  2. import com.javacode2018.aop.demo9.test1.Aspect1;
  3. import com.javacode2018.aop.demo9.test1.Service1;
  4. import org.junit.Test;
  5. import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
  6. public class AopTest9 {
  7. @Test
  8. public void test1() {
  9. try {
  10. //对应目标对象
  11. Service1 target = new Service1();
  12. //创建AspectJProxyFactory对象
  13. AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
  14. //设置被代理的目标对象
  15. proxyFactory.setTarget(target);
  16. //设置标注了@Aspect注解的类
  17. proxyFactory.addAspect(Aspect1.class);
  18. //生成代理对象
  19. Service1 proxy = proxyFactory.getProxy();
  20. //使用代理对象
  21. proxy.m1();
  22. proxy.m2();
  23. } catch (Exception e) {
  24. }
  25. }
  26. }

运行输出

  1. 前置通知,execution(void com.javacode2018.aop.demo9.test1.Service1.m1())
  2. 我是 m1 方法
  3. 前置通知,execution(void com.javacode2018.aop.demo9.test1.Service1.m2())
  4. execution(void com.javacode2018.aop.demo9.test1.Service1.m2()),发生异常:/ by zero

AspectJProxyFactory原理

@Aspect标注的类上,这个类中,可以通过通过@Pointcut来定义切入点,可以通过@Before@Around@After@AfterRunning@AfterThrowing标注在方法上来定义通知,定义好了之后,将@Aspect标注的这个类交给AspectJProxyFactory来解析生成Advisor链,进而结合目标对象一起来生成代理对象,大家可以去看一下源码,比较简单,这里就不多解释了。