嵌套调用方法时注解失效的原因 2020-05-11 16:24 > 参考链接: https://www.cnblogs.com/moxiaotao/p/9776964.html 同一个类中,在一个没有注解的方法A中调用另外一个有注解(比如@Async, @Transational)的方法B时,是不会触发B方法的注解的。 比如下面的例子: 有注解标注的方法addUser();没有注解标注的方法selUser()。在selUser()中调用addUser()则不会触发@Transactional注解。 ```java @Service public class UserService { @Resource private TestMapper testMapper; @Transactional public void addUser() { Test test = new Test(); test.setName("888"); test.setAge(888); testMapper.insertSelective(test); } public Test selUser() { Test test = testMapper.selectByPrimaryKey(1); addUser();//测试@Transactional是否起作用 System.out.println(test); return test; } } ``` 我们写一个简单的SpringBoot项目将这个service嵌进去。将日志级别设置为debug,这样能详细的看到是否执行了事务。 调用addUser()方法时,创建了一个事务去执行: `2020-05-07 14:58:01.563 DEBUG 101548 --- [nio-8081-exec-2] o.s.j.d.DataSourceTransactionManager : Creating new transaction with name [com.example.demo.service.UserService.addUser]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT` ![](https://minio.riun.xyz/riun1/2022-06-25_r4n9k39hy8GuEHUuGI.jpg) 而调用selUser()方法时,并没有创建事务执行: ![](https://minio.riun.xyz/riun1/2022-06-25_r4LYb7Xj6r3bSyEckO.jpg) 这验证了上面的结论。那这又是为什么呢? Spring在扫描bean时会扫描方法上的注解,当添加了@Async, @Transational等这些注解时,spring会为这个bean自动生成一个子类【代理类,proxy,[关于代理的文章点这里](http://riun.xyz/work/54)】,此子类继承原来的类,就是原来类的代理类。【比如例子中向addUser()添加注解@Transational时,spring扫描到时会生成一个继承于UserService的代理类UserServiceproxy】,代理类中为有注解的方法插入一个 startTransaction ()方法。 *伪代码:* ```java @Service public class UserServiceproxy$A { UserService userService = new UserService(); public void addUser() { startTransaction(); userService.addUser(); } /* 只有直接调用UserServiceproxy$A.addUser()时,才会调用到startTransaction(); */ public Test selUser() { userService.selUser(); /* 内部调用 userService.addUser() 而不是 UserServiceproxy$A.addUser() */ } } ``` 此时,当有注解的方法addUser()被调用时,实际上是调用代理类UserServiceproxy$A的addUser(),所以会执行到startTransaction(); 就能够开启事务。而调用没有注解的方法selUser()时,内部就是直接调用的自身的selUser(),自身的selUser()内部调用的是自身的addUser(),所以并不会开启事务。 那么如何解决这个问题呢?有两种方法: - 1、把这两个方法分开写到不同的类中(只需写在不同类中,selUser()方法不用添加注解); - 2、把注解加到类名上面(这样该类下的所有方法都拥有此注解的效果); --END--
发表评论