分析JDK代理与CGlib代理的区别,从而解读Spring AOP事务失效的问题的原因

动态代理和静态代理的区别?
动态代理是在程序运行时才生成目标代理类的class文件,而静态代理是在编译时就生成了目标代理类的class文件

有哪些常用的框架技术用到了动态代理?
Spring的AOP功能,可以用来加事务,加权限和加日志。
Mybatis Mapper的映射,实际上是把获取数据库连接,封装结果集返回等操作放在了动态代理中。
RPC框架,远程过程调用,通俗点说就是“像调用本地服务一样调用远程服务”,实际上就是把数据封装,网络传输等代码封装在了代理层。

JDK代理和CGlib代理有什么区别?
JDK动态代理的核心是生成一个跟目标类实现了同一接口的代理类的class文件,
局限性:因为JDK动态代理必须要继承Proxy类,所以它必须通过实现同一接口的方式来代理目标类

cglib动态代理的核心是生成一个目标类的子类,然后通过重写子类方法来实现代理逻辑
局限性:由于是通过继承来实现代理的,所以static,private,final的方法是无法被代理的

AOP的几个核心概念:
连接点:在哪些节点你可以切进去?(方法执行前,方法执行后,抛出异常时等)
切点:有哪些方法需要你切?
切面实现类:你切进去之后,要执行哪些逻辑?
通知:具体执行节点{
前置通知:在目标方法调用前需要执行的方法
后置通知:在目标方法完成后需要执行的方法
返回通知:在目标方法确定返回值后需要执行的方法
环绕通知:在目标方法调用前后执行的特殊逻辑
异常通知:在目标方法抛出异常时执行的逻辑
}

Spring在初始化容器,把一个个Bean加载到容器里的时候,就会判断这个类是否需要被代理,如果需要,那么生成的对象实际上就是目标类的代理对象,而不是目标类的对象。

Spring 2.0以后,AOP默认都是通过cglib来实现的了,但是在同一类中调用内部方法,AOP还是会失效,需要通过AOPContext.currentProxy来重新获取一个代理类来实现

Spring事务失效场景以及原因分析:

1.在没加@Transactional的方法中调用本类加了@Transactional的方法,但是事务不生效(同理还有异步注解不生效)

原因:因为spring的事务是通过代理来实现的,但是在同一类中调用内部方法,默认调用的是本身方法,而不是代理方法,所以会失效

2.private,static,final方法上,加@Transactional注解,但是事务不生效

原因:Spring的AOP是通过cglib来实现的,而cglib是通过生成一个目标类的子类,并且重写目标方法来实现代理的,private,static,final修饰的方法无法被继承或者重写,所以事务不生效

3.@Transactional如果不声明rollbackFor,那么默认之后回滚运行时异常

原因:spring的设定,有可能是因为spring认为编译时异常应该由开发者手动声明特殊的处理逻辑

Spring自带AOP通知的执行顺序:环绕通知前段-》前置通知-》环绕通知后段-》后置通知
分析JDK代理与CGlib代理的区别,从而解读Spring AOP事务失效的问题的原因_第1张图片

你可能感兴趣的:(java,动态代理,spring)