解决spring AOP中自身方法调用无法应用代理的问题
spring AOP中自身方法调用无法应用代理
如下例
public class MyServiceImpl implements MyService { public void do(){ //the transaction annotation won't work if you directly invoke handle() method with 'this' this.handle(); } @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public void handle() { //sth with transaction } }
如果直接调用this的handle()方法则事务无法生效,原因是spring的AOP是通过代理实现的,像这样直接调用本对象的方法是不会应用代理的。
可以使用如下两种方式修改代码以应用事务
(1)在MyServiceImpl中声明一个MyService对象
public class MyServiceImpl implements MyService { @Autowired private MyService myService; public void do(){ //use myService object myService.handle(); } @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public void handle() { //sth. with transaction } }
(2)使用AopContext类
public class MyServiceImpl implements MyService { public void do(){ //fetch current proxy objet from AopContext ((MyService)AopContext.currentProxy()).handle(); } @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public void handle() { //sth with transaction } }
注意,原生的AspectJ是不会有这种自身调用的问题的,因为它不是基于代理的AOP框架。
spring aop 内部方法调用事务不生效
方法1:
基于 proxy 的 spring aop 带来的内部调用问题可以使用 AopContext.currentProxy() 强转为当前的再调用就可以解决了
例如:
错误用法:
public Account getAccountByName2(String userName) { return this.getAccountByName(userName); }
修改为:
public Account getAccountByName2(String userName) { return ((AccountService)AopContext.currentProxy()).getAccountByName(userName); }
另外注意:要设置aop实体暴露出来。在springboot的application.java里面加上
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
方法2:
利用初始化方法在目标对象中注入代理对象
在目标对象类中注入spring上下文,通过context获取代理对象,并调用代理对象的方法。
注意:该方案对于scope为prototype的bean无法适用,因为每次获取bean时都返回一个新的对象。
方法2.1:
//延迟加载方式 private TestService testService; @Autowired @Lazy public void setTestService(TestService testService) { this.testService = testService; }
方法2.2:
import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import com.blog.common.aop.service.TestService; @Service public class TestServiceImpl implements TestService { @Autowired private ApplicationContext context; private TestService proxyObject; @PostConstruct // 初始化方法,在IOC注入完成后会执行该方法 private void setSelf() { // 从spring上下文获取代理对象(直接通过proxyObject=this是不对的,this是目标对象) // 此种方法不适合于prototype Bean,因为每次getBean返回一个新的Bean proxyObject = context.getBean(TestService.class); } public void methodA() throws Exception { System.out.println("method A run"); System.out.println("method A 中调用method B,通过注入的代理对象,调用代理对象的方法,解决内部调用实现的问题。"); proxyObject.methodB(); //调用代理对象的方法,解决内部调用失效的问题 } public void methodB() { System.out.println("method B run"); } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持猪先飞。
相关文章
- 这篇文章主要介绍了Spring AOP 对象内部方法间的嵌套调用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-29
Spring Cloud 中@FeignClient注解中的contextId属性详解
这篇文章主要介绍了Spring Cloud 中@FeignClient注解中的contextId属性详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-25Springboot如何实现Web系统License授权认证
这篇文章主要介绍了Springboot如何实现Web系统License授权认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-05-28- 这篇文章主要介绍了详解SpringCloudGateway内存泄漏问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-07-16
如何在Spring WebFlux的任何地方获取Request对象
这篇文章主要介绍了如何在Spring WebFlux的任何地方获取Request对象,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下...2021-01-26- @Autowired 注解的主要功能就是完成自动注入,使用也非常简单,但这篇文章主要给大家介绍了关于Spring为什么不推荐使用@Autowired注解的相关资料,需要的朋友可以参考下...2021-11-03
Springboot如何使用mybatis实现拦截SQL分页
这篇文章主要介绍了Springboot使用mybatis实现拦截SQL分页,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-19- 这篇文章主要介绍了自动设置安卓手机wifi代理的PowerShell脚本,帮助大家进行抓包测试,感兴趣的朋友可以了解下...2020-10-17
- 这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
- 这篇文章主要介绍了javascript实现方法调用与方法触发小结的相关资料,需要的朋友可以参考下...2016-03-30
Spring Data JPA 关键字Exists的用法说明
这篇文章主要介绍了Spring Data JPA 关键字Exists的用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-10tomcat启动完成执行 某个方法 定时任务(Spring)操作
这篇文章主要介绍了tomcat启动完成执行 某个方法 定时任务(Spring)操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-25- 这篇文章主要介绍了vue配置多代理服务接口地址操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-08
使用Maven 搭建 Spring MVC 本地部署Tomcat的详细教程
这篇文章主要介绍了使用Maven 搭建 Spring MVC 本地部署Tomcat,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-08-16- 这篇文章主要介绍了Spring Cloud负载均衡及远程调用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2021-09-18
- 这篇文章主要介绍了SpringMvc自动装箱及GET请求参数原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-19
- 这篇文章主要介绍了SpringMvc获取请求头请求体消息过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-17
- 这篇文章主要介绍了Springboot使用thymeleaf动态模板实现刷新,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-08-31
Idea打包springboot项目没有.original文件解决方案
这篇文章主要介绍了Idea打包springboot项目没有.original文件解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-26- 这篇文章主要介绍了spring boot 使用utf8mb4的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-20