1. 问题
今天搞注解拦截的时候发现有个方法没有被拦截到 具体代码如下
public void methodName(){
this.generateConclusionsByRecordID(recordID);
}
@Override
@Transactional(rollbackFor = Exception.class)
@CalculateAdditionInfo(recordId = "scaleRecordID", regenerate = true)
public void generateConclusionsByRecordID(String scaleRecordID) throws Exception {
//dosomething()
}
分析原因可能是 this指向目标对象,走的不是代理 所以无法被拦截到,因此调用generateConclusionsByRecordID()
方法不会执行事物切面,即不会执行事务增强,因此generateConclusionsByRecordID()
的事务@Transactional
不会执行。
2. 解决办法
使用AopContext.currentProxy()
函数调用方法
public void methodName(){
((ServiceClass)AopContext.currentProxy()).generateConclusionsByRecordID(recordID);
}
3. 可能遇到的问题
3.1 Cannot find current proxy: Set ‘exposeProxy’ property on Advised to ‘true’ to make it available.
出现这个报错通常是因为使用了AopContext.currentProxy()
函数却没有添加相应的配置造成的。
通过注解添加配置(加在启动类上):
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
或通过xml配置文件添加配置:
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
4. 总结
Spring是采用动态代理(AOP)实现对bean的管理和切片,它为我们的每个class生成一个代理对象。
只有在代理对象之间进行调用时,可以触发切面逻辑,也就是切面才可以切进去,才能执行切面里编写的代码。
而在同一个class中,方法B调用方法A,调用的是原对象的方法,而不通过代理对象。所以Spring无法切到这次调用。 获取本对象的代理对象,再进行调用这个类里面的其他方法,那么被调用的那个方法上面如果有切面 那么切面就可以生效了
这样下面的dosomething上的@Transactional开启事物方法就可以生效了