在我们使用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被增强。