iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >解决spring AOP中自身方法调用无法应用代理的问题
  • 827
分享到

解决spring AOP中自身方法调用无法应用代理的问题

2024-04-02 19:04:59 827人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录spring aop中自身方法调用无法应用代理如下例可以使用如下两种方式修改代码以应用事务(1)在MyServiceImpl中声明一个MyService对象(2)使用AopCon

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");
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: 解决spring AOP中自身方法调用无法应用代理的问题

本文链接: https://www.lsjlt.com/news/133877.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作