内部调用自定义注解方法,AOP不生效
之前遇到过的@CacheEvict注解和@Transactional注解内部调用不生效,也是同样的原因
自定义注解#
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
String value();
}
自定义切面#
@Slf4j
@Aspect
@Component
public class DynamicDataSourceAspect {
@Before("@annotation(targetDataSource))")
public void switchDataSource(JoinPoint point, TargetDataSource targetDataSource) {
log.info("something to do before...")
}
@After("@annotation(targetDataSource))")
public void restoreDataSource(JoinPoint point, TargetDataSource targetDataSource) {
log.info("something to do after...")
}
}
问题代码#
@Slf4j
@Component
public class TestRunner implements CommandLineRunner {
@Override
public void run(String... args) {
query();
}
@TargetDataSource("brf")
public void query() {
log.info("query");
}
}
执行现象#
只打印出了query,没有触发AOP逻辑,切面中环绕代码没有执行
原因#
这是由于 Spring AOP (包括动态代理和 CGLIB 的 AOP) 并不是扩展了一个类(目标对象(Target Object)), 而是使用了一个代理对象(AOP Proxy Object)来包装目标对象, 并拦截目标对象的方法调用. 导致在目标对象中调用自己类内部实现的方法时, 这些调用并不会转发到代理对象中.
在调用query()时,此时的调用者已经是目标对象了,不会再执行代理对象的AOP逻辑了。
解决方案#
1. 注入代理对象调用目标方法#
@Slf4j
@Service
public class TestRunner implements CommandLineRunner {
@Autowired
private TestRunner testRunner;
@Override
public void run(String... args) {
testRunner.query();
}
@TargetDataSource("brf")
public void query() {
log.info("query");
}
}
不过会出现循环依赖问题
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
可以增加配置,解决该错误
spring:
main:
allow-circular-references: true
2. 将目标方法写到别的类中,不再内部调用#
比较常规,就不写代码举例了
3. 使用@Lazy延迟加载bean#
@Slf4j
@Service
public class TestRunner implements CommandLineRunner {
@Lazy
@Autowired
private TestRunner testRunner;
@Override
public void run(String... args) {
testRunner.query();
}
@TargetDataSource("brf")
public void query() {
log.info("query");
}
}
作者:colfish
出处:https://www.cnblogs.com/colfish/p/17577886.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!