一、AOP有哪几种
AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ(可以基于注解使用);而动态代理则以SpringAOP为代表。
静态代理是编译期实现,即编译时就将切面代码织入到生成的字节码中。而动态代理是运行期实现,即运行时在内存中临时生成一个aop对象。可想而知前者拥有更好的性能。
二、spring两种AOP的区别
spring AOP的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
1、jdk动态代理
JDK动态代理会通过反射来生成一个代理类,代理类继承Proxy类,且和原始目标类实现同一个接口。
代理类的关系如下代码所示:
public final class TestProxy extends Proxy implements TestService{}
由于java不允许多继承,所以只有在目标类实现了接口时,spring才会使用jdk动态代理。
另外,jdk动态代理会增加一个InvocationHandler类来负责增加代理逻辑和调用具体实现类的方法。这样如果所有方法都是相同的增强,就不用所有方法都加上重复代码了。
public class InvocationHandlerImpl implements InvocationHandler {
TestService target;
public InvocationHandlerImpl(TestService target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置代码
doSomeThingBefore();
// 被代理的方法代码
Object invoke = method.invoke(target, args);
// 后置代码
doSomeThingAfter();
return invoke;
}
private void doSomeThingBefore() {
System.out.println("doSomeThingBefore!");
}
private void doSomeThingAfter() {
System.out.println("doSomeThingAfter!");
}
}
在实际业务调用过程中,会请求代理类,代理类再通过InvocationHandler来调用增强后的原始类的方法。
2、CGLIB动态代理
如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。
CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的,诸如private的方法也是不可以作为切面的。
3、区别
- jdk动态代理无法对接口中没有的public方法进行增强,而cglib可以
- jdk动态代理要求目标类实现接口,cglib不用
- java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理;而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
注意:
spring中使用@AspectJ注解的配置方式,仅仅是使用了aspectj包中的注解,还是spring Aop
三、参考资料