基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别

基于JDK动态代理:

<tx:annotation-driven transaction-manager="txManager"/> 

该配置方式默认就是JDK动态代理方式

 

运行单元测试,核心日志如下: 


基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别_第1张图片


到此我们可以看到事务起作用了,也就是说即使把@Transactional放到接口上 基于JDK动态代理也是可以工作的。

基于CGLIB类代理:

<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

该配置方式是基于CGLIB类代理

 

启动测试会报错,No Session found for current thread,说明事务没有起作用


基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别_第2张图片

如果将注解放在具体类上或具体类的实现方法上才会起作用。
package cn.javass.common.service.impl;  
public abstract class BaseServiceImpl implements BaseService {  
    @Transactional() 
    @Override  
    public int countAll() {  
        return baseDao.countAll();  
    }  
}

运行测试类,将发现成功了,因为我们的UserService继承该方法,但如果UserService覆盖该方法,如下所示,也将无法织入事务(报错):
package cn.javass.demo.service.impl;  
public class UserServiceImpl extends BaseServiceImpl implements UserService {  
    //没有@Transactional  
    @Override   
    public int countAll() {  
        return baseDao.countAll();  
    }  
}  


基于aspectj的
<tx:annotation-driven transaction-manager="txManager" mode="aspectj" proxy-target-class="true"/>  
在此就不演示了,我们主要分析基于JDK动态代理和CGLIB类代理两种的区别。

结论:

基于JDK动态代理 ,可以将@Transactional放置在接口具体类或者具体类的实现方法上。

基于CGLIB类代理,只能将@Transactional放置在具体类或者具体类的实现方法上。

 

因此 在实际开发时全部将@Transactional放到具体类上,而不是接口上。

你可能感兴趣的:(基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别)