1 AspectJ 是编译时增强的AOP框架,属于静态代理,但是代码组织上优于单纯使用java静态代理设计模式
2 SpringAOP 使用动态代理,与AspectJ没有任何关系,只不过使用了和AspectJ一样的注解,利用类似的概念、语法等(理解为向经典致敬),所以容易误认为SpringAOP使用AspectJ,如SpringAOP中的注解:@Aspect @Around @After,底层完全是SpringAOP自己一套东西
3 Spring 底层使用动态代理,可能是java原生动态代理,也可能是CGLib,默认规则如下
(1)如果实例实现了接口,如XxxServiceImpl implements XxxService,则底层使用JDK动态代理,比如@Transactional加到service方法上是JDK动态代理
(2)如果没有实现接口,类似在XxxController中的Http入口增强方法(如自定义增强注解:@ThirdToken),则使用CGLib代理,如在Http入口方法中答应容器中的XxxController.getClass(),出现如下:XxxController$$EnhancerBySpringCGLIB$$630fe5ae
(3)如果强制使用CGLib,则尽管实现接口类,也强制使用CGLib,但需要配置:
xml:
<aop:aspectj-autoproxy proxy-target-class="true"/>
注解(springboot只要加上AOP依赖后,默认是加上@EnableAspectJAutoProxy,只不过spring.aop.proxy-target-class=false)
@EnableAspectJAutoProxy(proxyTargetClass = true),默认情况下的代理使用原则,即不要配置proxy-target-class="true"
java动态代理主要依靠InvocationHandler实现,CGLib动态代理,主要依靠代理类继承父类,重写父方法实现
4 @Transactional内部调用失效
public class ASerivceImpl implements ASerivce{
// 自注入
@Autowared
private ASerivce aService;
public funcA(){
this.funcB();
aService.funcB();
}
@Transactional
public funcB(){
}
}
调用funcA,funcB上的事务注解是不起效的,因为相当于是this.funcB()是未被Spring增强过的方法,移动要从Spring容器中取出来的才是增强过的方法