SpringAOP不生效的情况

在使用SpringAOP的过程中不知道大家有没有遇到这样一个问题,就是我对一个方法做了AOP的增强,但是在内部方法的调用过程中,却发现它并没有按照预期设定的那样执行AOP的增强。

下面我通过一个例子来说明这种情况。
在这里插入图片描述
首先先在数据库中建一个表,这个表只有两列,如图。

然后写一个DataService类,在这个类中,主要实现一个insert方法,在insert方法上加了一个@Transactional的注解;一个insertRollback的方法,在插入数据之后抛出RuntimeException异常,上面加一个注解标明在遇到RuntimeException的异常时做一个rollback回退。

@Transactional
public void insert(int i,String value){        
    jdbcTemplate.update("insert into springtest values(?,?)",i,value);
}
@Transactional(rollbackFor = RuntimeException.class)
public void insertRollback(int i,String value){
    System.out.println("现在是insertRollback方法,插入值为"+value);
    jdbcTemplate.update("insert into springtest values(?,?)",i,value);
    throw new RuntimeException();
}

然后printAllData方法把表中所有数据都打印出来。

public void printData(){
    System.out.println("打印所有数据");
    jdbcTemplate.queryForList("select * from springtest")
            .forEach(r->System.out.println(r.get("id")+" "+r.get("text")));
}

再通过invokeMethod方法对上面的方法做内部调用。

public void invokeMethod(){
    try {
        insertRollback(4,"invokeMethod");
    }catch (RuntimeException e){
        System.out.println("调用invokeMethod方法时异常");
    }}

我们可以看一下用invokeMethod方法来调用insertRollback时跟直接调用insertRollback,这个事务是不是都会生效。

private void demo1(){
    s.insert(2,"insert");
    s.printData();
    try {
        s.insertRollback(3,"insertRollback");
    }catch (RuntimeException e){
        System.out.println("调用insertRollback方法时异常");
    }
    s.printData();
    s.invokeMethod();
    s.printData();
}

在这里插入图片描述
运行第一个insert方法之后,打印所有数据可以看到表中现在有一个id是2,text是insert的一行数据。

然后执行insertRollback方法插入id是3,text是insertRollback的数据,我们看到数据并没有添加进去,因为我们设定了在插入数据之后抛出RuntimeException异常,所以在插入数据之后,便会回滚。

这是正常使用insertRollback,事务是生效的,与此同时,我们从第三条invokeMethod方法的执行结果来看,id是4,text是invokeMethod的数据插入了表中而没有回滚,说明这种情况下insertRollbcak的事务并没有生效。

学过SpringAOP的话我们都知道,SpringAOP是对我们的Bean做了一个动态的增强,它给我们去做了Proxy的一个对象,其实也就是执行在我的一个代理对象上的一些操作

如果我是在一个类的内部方法调用,就像上面我用invokeMethod去调用我的insertAndRollBack的时候,程序并没有去走SpringAOP的一个增强逻辑。

知道了原理,那么解决上面这种问题的方法就有了,既然不能直接通过this的这种方式在一个内部方法中去调用AOP增强的方法使其生效,那么就调用SpringAOP增强过的这个Proxy对象。

这里我提供三种方法。让我们回到刚才的例子。

第一种,也是最简单直观的,我去Autowired自己的一个bean进来。

@Autowired
private DataService dataService;

然后写一个invokeWithSelf的方法通过注入的DataService的bean来调用insertRollbcak。

public void invokeWithSelf(){
    try {
        dataService.insertRollback(5,"invokeWithSelf");
    }catch (RuntimeException e){
        System.out.println("调用invokeWithSelf方法时异常");
    }
}

第二种,通过Spring的ApplicationContextAware的方式,首先把我的ApplicationContext拿到,这里我通过Autowired的方式得到ApplicationContext。

@Autowired
private ApplicationContext applicationContext;

然后写一个invokeWithAC方法通过getBean的方式去拿到我的DataService的bean。

public void invokeWithAC(){
    try {
        ((DataService)applicationContext.getBean("dataService")).insertRollback(6,"invokeWithAC");
    }catch (RuntimeException e){
        System.out.println("调用invokeWithAC方法时异常");
    }
}

第三种可以用一些AOP的辅助方法,可以拿到当前的Proxy的代理对象。

我这里试了一下AOPContext, 这里写了一个invokeWithAopContext的方法,通过调用AopContext.currentProxy(),取到当前bean的代理,最后调用insertRollbcak。

public void invokeWithAopContext(){
    try {
        ((DataService) AopContext.currentProxy()).insertRollback(7,"invokeWithAopContext");
    }catch (RuntimeException e){
        System.out.println("调用invokeWithAopContext方法时异常");
    }
}

但是这边调currentProxy方法时,需要在程序入口类上方设置@EnableAspectJAutoProxy注解的属性exposeProxy 为true才能使其生效。

我们来实验一下。

private void demo2(){
    s.invokeWithAopContext();
    s.printData();
    s.invokeWithSelf();
    s.printData();
    s.invokeWithAC();
    s.printData();
}

在这里插入图片描述
从结果可以看到这些方式都可以实现内部调用方法的AOP增强,我个人觉得第一种方法比较方便。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP未生效的原因可能有以下几种情况。 首先,如果要增强的类或方法没有被Spring管理,那么AOP就无法生效。这种情况下,需要将目标类或方法注入到Spring容器中才能实现AOP的增强效果。 其次,如果要被增强的类或方法同时被Spring和Spring MVC扫描,可能会导致AOP失效。这是因为在Spring MVC容器中重新实例化的对象并没有被AOP代理,而是由Spring MVC容器直接管理。为了解决这个问题,我们需要确保AOP配置中的切点表达式声明与要切入的类和方法在同一个容器中。 另外,如果要增强的方法被同类的方法调用,也可能导致AOP不生效。这是因为AOP是在目标方法调用时才会生效,而同类的方法调用不会触发AOP。要解决这个问题,可以将目标方法抽取为单独的方法,然后在原来的方法和其他使用该方法的地方进行调用。 还有一种情况是,如果使用了注解方式进行AOP,但没有开启注解支持,也会导致AOP不生效。要解决这个问题,需要在Spring配置文件中添加注解支持的配置。 综上所述,要解决Spring AOP不生效的问题,需要注意以上几种情况,并根据具体情况进行相应的修改和调整。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Spring Aop失效的情況及解决办法](https://blog.csdn.net/weixin_43790613/article/details/113091496)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值