前言:在重构公司的风控系统的时候,发现旧代码中经常出现获取当前service的bean在调用方法的情况。后来才发现其中的问题。
如下:
private AccountActionProfileService me() {
return applicationContext.getBean(AccountActionProfileService.class);
}
@Transactional
public void addAccountActionProfile() {
.......
if (.....) {
me().verifyBanAccountRule(target);
}
}
@Async
public void verifyBanAccountRule(AccountActionProfileEntity accountAction, String originalAccountName) {
.........
}
后来才发现若没有me()
方法而直接使用verifyBanAccountRule
方法的话,该方法并没有被新的线程执行,还是在旧线程中串行执行。通过谷歌搜索了一下,才知道其原因。
原因
了解过spring的aop原理的同学应该都知道spring的aop是基于cglib或jdk动态代理生成代理类,而我们在方法中直接调用带有Aop注解的方法,实际上是通过当前对象的this指针访问该方法,此时当前对象并不是代理对象,故上面公司的旧代码使用的是从spring容器中获取bean,再通过bean来调相应的方法。
@Service
public class DmzService {
public void saveAB(A a, B b) {
saveA(a);
saveB(b);
}
@Transactional
public void saveA(A a) {
dao.saveA(a);
}
@Transactional
public void saveB(B b){
dao.saveB(a);
}
}
saveAB
方法中调用了本类中的saveA
跟saveB
方法,这就是自调用。自调用会导致aop失效。
解决方法
从spring容器中获取bean,再通过bean来调相应的方法。~~~~
@Autowired
private ApplicationContext applicationContext;
private AccountActionProfileService me() {
return applicationContext.getBean(AccountActionProfileService.class);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。