【发布时间】:2020-09-01 09:13:53
【问题描述】:
我尝试在springboot中使用bytebuddy实现aop。代码如下:
package klordy.learning.annotation;
@Target(METHOD)
@Retention(RUNTIME)
@Documented
public @interface CostTime {
}
package klordy.learning.agent;
public class Agent {
private static Agent instance = new Agent();
private Logger logger = LoggerFactory.getLogger(Agent.class);
private Agent() {}
public static Agent getInstance(){ return instance; }
public void install() {
ByteBuddyAgent.install();
AgentBuilder.Listener listener = new AgentBuilder.Listener() {
// do nothing
...
};
new AgentBuilder.Default()
.type(ElementMatchers.nameStartsWith("klordy.learning"))
.transform((builder, typeDescription, classLoader, module) ->
builder.visit(Advice.to(TimeAdvice.class).on(ElementMatchers.isAnnotatedWith(named("klordy.learning.annotation.CostTime")))))
.with(listener)
// *** added as supposed, but still seems not work.
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.installOnByteBuddyAgent();
logger.info("byte buddy modification done.");
}
}
public class TimeAdvice {
@Advice.OnMethodEnter
static long enter(@Advice.AllArguments Object args[], @Advice.Origin Method method){
return System.currentTimeMillis();
}
@Advice.OnMethodExit
static void exit(@Advice.Enter long startTime,
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
@Advice.Origin Method method,
@Advice.Thrown Throwable throwable){
if(throwable != null){
System.out.println("error func " + System.currentTimeMillis());
}else {
System.out.println("func takes " + (System.currentTimeMillis() - startTime));
}
}
}
springboot的监听器如下:
public class AppEnvListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
private Logger logger = LoggerFactory.getLogger(AppEnvListener.class);
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent) {
Agent.getInstance().install();
logger.info("finished byte buddy installation.");
}
}
最后在springboot启动时注册监听器:
@SpringBootApplication
@ComponentScan(basePackages = "klordy.learning")
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringBootDemoApplication.class);
// register listener
application.addListeners(new AppEnvListener());
application.run(args);
}
}
当我启动应用程序时,调试记录器显示正常。但是,处理请求时 aop 不起作用。我究竟做错了什么?我很困惑……
【问题讨论】:
-
像往常一样,Rafael 关于 BB 的回答是正确的。只是出于好奇:为什么在 Spring Boot 中您已经拥有两个成熟的 AOP 框架(Spring AOP 和 AspectJ)可供使用时使用 BB?
-
有兴趣和新来的BB。只是为了学习。 @kriegaex
-
如果你想专心学习BB,不妨从更简单的Java SE环境入手,尝试有无Java代理,了解API后再切换到容器或应用服务器环境,以减少系统中变量或“移动部件”的数量。 ??????
-
????感谢您的建议,我会接受并尝试了解有关 API 的更多信息。
标签: java spring-boot aop byte-buddy