本文介绍Spring中在同一个类下进行方法调用时,注解可能失效的解决方案
概述
众所周知,当SpringBoot中一个类下有a、b两个方法时,如果该类内的a方法直接调用b方法,则b方法上基于代理实现的注解会无法生效。典型地有:@Transactional、@Async、@Retryable注解。例如下述例子
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Service public class DogService {
public void sayHi(){ sayBye(); }
@Async public void sayBye() { ... } }
|
解决方案
方法拆分到不同类中
简单粗暴地办法,是将同类中的两个方法拆分到两个类当中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Service public class DogService1 {
@Autowired private DogService2 dogService2;
public void sayHi(){ dogService2.sayBye(); }
}
...
@Service public class DogService2 {
@Async public void sayBye() { ... } }
|
自我注入
在该类中进行自我注入,然后通过注入后的实例来进行调用。如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Service public class DogService3 {
@Autowired private DogService3 dogService3;
public void sayHi(){ dogService3.sayBye(); }
@Async public void sayBye() { ... } }
|
此举在低版本SpringBoot版本中可能会提示依赖循环,可在配置文件application.properties中添加下述配置
1 2
| spring.main.allow-circular-references=true
|
获取代理对象
之所以同类下方法调用会导致注解失效,是因为此时没有走代理进行调用。既然如此,那么解决思路就是获取类的代理对象,然后通过该代理进行方法调用。首先在启动类上添加 @EnableAspectJAutoProxy 注解。注意需要将exposeProxy属性设置为true,以实现暴露代理对象
1 2 3 4 5 6 7
| @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) @SpringBootApplication public class SpringBoot1Application { public static void main(String[] args) { SpringApplication.run(SpringBoot1Application.class, args); } }
|
然后在业务代码中即可通过AopContext获取代理对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Service public class DogService4 {
public void sayHi(){ DogService4 thisServiceProxy = (DogService4)AopContext.currentProxy(); thisServiceProxy.sayBye(); }
@Async public void sayBye() { ... } }
|