当前位置:LBNB > 实用知识 > 解决spring(AOP中自身方法调用无法应用代理的问题)

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

解决spring,AOP中自身方法调用无法应用代理的问题,萝卜牛逼网带你了解更多相关信息。

目录
  • spring AOP中自身方法调用无法应用代理
    • 如下例
    • 可以使用如下两种方式修改代码以应用事务
      • (1)在MyServiceImpl中声明一个MyService对象
      • (2)使用AopContext类
  • spring aop 内部方法调用事务不生效
    • 方法1:
      • 方法2:

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

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

      另外注意:要设置aop实体暴露出来。在springboot的application.java里面加上

      @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)

      方法2:

      利用初始化方法在目标对象中注入代理对象

      在目标对象类中注入spring上下文,通过context获取代理对象,并调用代理对象的方法。

      注意:该方案对于scope为prototype的bean无法适用,因为每次获取bean时都返回一个新的对象。

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

      方法2.1:

      //延迟加载方式private TestService testService;@Autowired@Lazypublic 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;@Servicepublic 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\");    }}

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持趣讯吧。