Spring aop-本类方法调用切面增强失效

在我们使用spring的时候,往往会遇到在本类被aop代理的时候,访问本类其他被代理的方法,发现并没有被代理。那么我们应该如何实现呢

xml配置

       
       <aop:aspectj-autoproxy expose-proxy="true"/>

java

@Service
public class AService {
    @Transactional(propagation = Propagation.REQUIRED)
    public void a(){
        System.out.println("---------------a start--------------------");
        //此方法相当于调用当前线程中的Aservice的代理类,是保存在ThreadLocal中的
        //1 ((AService) AopContext.currentProxy()).b();
        //2 this.b();
        System.out.println("---------------a end--------------------");
        //throw new RuntimeException("i want run , but i have some error");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void b(){
        System.out.println("----------------b start-------------------");
        //throw new RuntimeException("i want run , but i have some error");
        System.out.println("----------------b end-------------------");
    }
}

详情请看 文章,点击进入
在说一下事务传播行为

1. 如果在b方法中抛出runtime Exception的时候,那么a方法回滚
2. 如果在a方法中抛出runtime Exception的时候,那么b方法不回滚

首先分析一下第一种情况
1. b在执行的时候会新建一个事务并把当前a的事务挂起,b在执行的时候回滚。那么a也会接受到此exeception并回滚
2. 在a方法中抛出异常并回滚,但是现在b已经执行完毕了,已经commit了,那么只有a会回滚。

=====================2017 - 04 - 23=========================

现在发现上面说的都是屁话
完全不知道当时在想些什么

现在重新陈述一遍

现在的需求是 我在a方法中直接调用的b的时候,会发生的状况就是 a 回滚的b也回滚了 很气 虽然没有合适的业务场景说明 a回滚的时候不需要b回滚。但是我们需要a回滚的情况下 b不需要回滚。

如果我们直接调用this.b()的话 确实是 ab 一起回滚。因为都是在一个事务里面。

但是我们的初衷在b上面标注b开启一个新的事务。那么这种情况下
b是一个新的事务。a回滚的时候b已经commit了
那么我们目的就达到了。
这样的需求的解决方法就是: 在a调用的b方法上是已经被增强的b方法。那么我们就需要找到此时的代理类。增强了b方法的类。也就是当前线程中的代理类。

spring提供了这个配置

在配置文件中配置暴露代理类就好了

       
       <aop:aspectj-autoproxy expose-proxy="true"/>

通过下面实现日志的切面说明一下

注解

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PrintLog {
}

切面类

@Component
@Aspect
public class LogAspectj {
    private final static Logger loggger = LoggerFactory.getLogger(LogAspectj.class);

    @Pointcut("@annotation(com.wuhulala.studySpring.annotation.PrintLog)")
    public void log(){
    }

    @Before("log()")
    public void before(JoinPoint joinPoint){
        loggger.debug(joinPoint.getSignature().getName()+" : start.....");
    }

    @After("log()")
    public void after(JoinPoint joinPoint){
        loggger.debug(joinPoint.getSignature().getName()+" : end.....");
    }
}

测试方法

@Service
public class AOPService {
    @PrintLog
    public void a(){
        System.out.println("---------------a start--------------------");
        ((AOPService) AopContext.currentProxy()).b();
        //this.b();
        System.out.println("---------------a end--------------------");
    }

    @PrintLog
    public void b(){
        System.out.println("----------------b start-------------------");
        System.out.println("----------------b end-------------------");
    }
}

this.b() 打印结果

21:40:37,957 DEBUG com.wuhulala.studySpring.Aspectj.LogAspectj (28) - a : start.....
---------------a start--------------------
----------------b start-------------------
----------------b end-------------------
---------------a end--------------------
21:40:37,976 DEBUG com.wuhulala.studySpring.Aspectj.LogAspectj (35) - a : end.....

((AService) AopContext.currentProxy()).b()打印结果

21:41:57,381 DEBUG com.wuhulala.studySpring.Aspectj.LogAspectj (28) - a : start.....
---------------a start--------------------
21:41:57,399 DEBUG com.wuhulala.studySpring.Aspectj.LogAspectj (28) - b : start.....
----------------b start-------------------
----------------b end-------------------
21:41:57,399 DEBUG com.wuhulala.studySpring.Aspectj.LogAspectj (35) - b : end.....
---------------a end--------------------
21:41:57,400 DEBUG com.wuhulala.studySpring.Aspectj.LogAspectj (35) - a : end.....

可见第二种是我们需要的。我们需要b被增强。

你可能感兴趣的:(spring,framework)