AspectJProxyFactory
,可能大家对这个比较陌生,但是@Aspect
这个注解大家应该很熟悉吧,通过这个注解在spring环境中实现aop特别的方便。
而AspectJProxyFactory
这个类可以通过解析@Aspect
标注的类来生成代理aop代理对象,对开发者来说,使创建代理变的更简洁了。
先了解几个概念
文中会涉及几个概念,先了解一下。
- target
用来表示目标对象,即需要通过aop来增强的对象。
- proxy
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链,进而结合目标对象一起来生成代理对象,大家可以去看一下源码,比较简单,这里就不多解释了。