SpringBootCGLIBAOP解决Spring事务,对象调⽤⾃⼰⽅法事务
失效.
对于像我这种喜欢滥⽤AOP的程序员,遇到坑也是习惯了,不仅仅是事务,其实只要脱离了Spring容器管理的所有对象,对于SpringAOP的注解都会失效,因为他们不是Spring容器的代理类,SpringAOP,就切⼊不了
当然可以使⽤原⽣ASPECTJ,不⽤SpringAOP,但是基于⽣态链问题,还是尽量使⽤SpringAOP
这⾥简单说⼀下,Spring如何选择使⽤CGLIB,或者是JDK代理,
简单来说,如果实现了某个接⼝,那么Spring就选择JDK代理(不⼀定),如果没有,那么就选择CGLIB代理,说起来简单,Spring还会闹脾⽓,不代理呢点击:
⼀直以来⽐较多的情况是在Controller 调⽤Service 的⽅法,把事务直接在Service的⽅法上,妥妥的没问题,事务正常执⾏
考虑以下问题: 同对象的⽅法B 调⽤⾃⼰的⽅法A,这⾥的事务将会失效(严格上来说,只要对⽅法A使⽤注解AOP均会失效),原因是因为这⾥的this.调⽤的并不是Spring的代理对象
@Service
public class ClassA{
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA(){
}
/**
* 这⾥调⽤methodA() 的事务将会失效
*/
public void methodB(){
}
}
最简单的解决⽅法为:(代理模式为JDK 的情况下(根据接⼝代理))
@Service
public class ClassA extends BaseClass{
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void methodA(){
}
/**
* 这⾥调⽤methodA() 的事务将会失效
*/
public void methodB(){
//使⽤getBean
((Bean("classA")).methodA();
}
}
第⼆种⽅式:
解决第⼀步: 必须
SpringBoot:注解开启cglib代理,开启 exposeProxy = true,暴露代理对象 (否则AopContext.currentProxy()) 会抛出异常
@EnableAspectJAutoProxy(exposeProxy = true)
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
配置⽅式:配置⽅式下,我⽤的是SpringBoot 1.5.4没有到exposeProxy的选项,所以建议使⽤注解式.
传统Spring配置⽂件
XML
<aop:aspectj-autoproxy expose-proxy="true"/>
第⼆步(需要保证Spring对这个bean创建了代理对象,基本上涉及到Aop的⽅法的类,都会创建代理对象) 可以⽤以下代码判断/**
* Created by laizhenwei on 19:37 2017-10-14
springboot aop*/
@Service("classImplProxy")
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class ClassImplProxy implements IClass {
@Override
@Transactional
public void sysout() {
}
//是否代理对象
@Override
public boolean isAopProxy() {
return AopUtils.isAopProxy(AopContext.currentProxy());
}
//是否cglib 代理对象
@Override
public boolean isCglibProxy() {
return AopUtils.isCglibProxy(AopContext.currentProxy());
}
//是否jdk动态代理
@Override
public boolean isJdkDynamicProxy() {
return AopUtils.isJdkDynamicProxy(AopContext.currentProxy());
}
}
获取代理对象
@Service
public class ClassA{
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA(){
}
public void methodB(){
//⼿动获取此对象Spring的代理类
((ClassA)AopContext.currentProxy()).methodA();
}
}
第三种⽅式
直接在当前类@Autowire 或者@Resource 注⼊⾃⼰,然后⽤注⼊的bean 调⽤⽅法
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论