关于@transactional使用在接口上的问题

JanWarlen 2017-06-06 10:07:03
引用
虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。

很多地方的技术分享都说到了这,但是我现在看到一个项目代码,Dao接口继承CrudRepository,然后注解使用在dao接口上。

@Component
@Transactional
public interface UserDao extends CrudRepository<User,Integer>{
}

Q1:基于接口的代理究竟是什么意思?
Q2:如上的在接口的注解能否生效?是否会有什么特殊效果?
...全文
3556 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
陪公主读书 2018-10-10
  • 打赏
  • 举报
回复 2
spring aop是采用动态代理的方式实现,动态代理有两种方式实现:
引用
1、java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 2、cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
spring使用这两种方式的策略是:
引用
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 。 2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP 。 3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换。
回答Q1: 基于接口即是说的jdk利用反射实现的动态代理的方式。 回答Q2: 会生效的,不管你这个dao有没有实现类(如果是mybatis对应的mapper,mybatis会用jdk的动态代理生成一个实现类的)。不会有什么特殊效果。 再回答你一个疑问,你引用中提到的【因为这只有在使用基于接口的代理时它才会生效】,这里提到的这个其实是这个意思:

class ServiceAImpl implements IServiceA {
   
   @Transactional(propagation = Propagation.REQUIRED,readOnly = false,rollbackFor = Exception.class)
   void test1(){
    ......
   }
   
   @Transactional(propagation = Propagation.REQUIRED,readOnly = false,rollbackFor = Exception.class)
   void test2(){
    ......
   }
}

class TestController {
  @Autowired
  private IServiceA serviceA ;

  void test(){
    //这里test1和test2上面的注解事务是生效的,因为是走的接口。
    serviceA.test1();
    serviceA.test2();
  }
}

//如若换成另一种结构就不同了。

class ServiceAImpl implements IServiceA {
   
   @Transactional(propagation = Propagation.REQUIRED,readOnly = false,rollbackFor = Exception.class)
   void test1(){
    test2();
   }
   
   @Transactional(propagation = Propagation.REQUIRED,readOnly = false,rollbackFor = Exception.class)
   void test2(){
    ......
   }
}

class TestController {
  @Autowired
  private IServiceA serviceA ;

  void test(){
    //这里test1上面的注解事务是生效的,因为是走的接口。
    //test1实现里面调用test2,则test2上面的注解是不生效的,因为实现类内部调用方法不走动态代理。
    serviceA.test1();
  }
}

参考文章:https://blog.csdn.net/bntX2jSQfEHy7/article/details/79040349 如若你非要在实现类内部调用也要走动态代理,也是有解决方案的,答案就在我给你的链接里面。

67,515

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧