gpt4 book ai didi

java - Spring 启动时带 aop 的 bytebuddy 不起作用

转载 作者:行者123 更新时间:2023-12-04 08:58:57 33 4
gpt4 key购买 nike

我尝试使用bytebuddy在springboot中实现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 不起作用。我究竟做错了什么?我很迷惑...

最佳答案

好的,我想我通过使用 Spring Boot 重新创建您的情况发现了您的问题。不过,如果没有 Spring,它也会发生。基本上你打this problem .
因此,如果您将建议修改为 @Advice.OnMethodExit(onThrowable = Throwable.class) ,你应该没问题。您还应该添加 .disableClassFormatChanges()给你的经纪人,顺便说一句。它有助于避免重新转换以前加载的类的问题。 JVM 要求不要在结构上更改它们。
我怎么知道发生了什么?我在 ByteBuddy 中激活了控制台日志记录。以前我使用过你的监听器,让它记录每一个 Action ,所以我可以看到 BB 实际上被触发了。但是 BB 日志确实显示了由于您错误使用 @Advice.Thrown 而导致的异常。 (在建议注释中没有 onThrowable = Throwable.class)。

public void install() {
ByteBuddyAgent.install();
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(RETRANSFORMATION)
.with(AgentBuilder.RedefinitionStrategy.Listener.StreamWriting.toSystemError())
.with(AgentBuilder.Listener.StreamWriting.toSystemError().withTransformationsOnly())
.with(AgentBuilder.InstallationListener.StreamWriting.toSystemError())
.type(ElementMatchers.nameStartsWith("klordy.learning"))
.transform((builder, typeDescription, classLoader, module) ->
builder.visit(
Advice
.to(TimeAdvice.class)
.on(isAnnotatedWith(named("klordy.learning.annotation.CostTime")))
)
)
.installOnByteBuddyAgent();
logger.info("byte buddy modification done.");
}

关于java - Spring 启动时带 aop 的 bytebuddy 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63656920/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com