gpt4 book ai didi

java - 将静态方法添加到类并委托(delegate)给现有方法

转载 作者:行者123 更新时间:2023-11-30 07:47:17 29 4
gpt4 key购买 nike

这是我的。代理:

public static void premain(String args, Instrumentation inst) throws Exception {
new AgentBuilder.Default()
.type(ElementMatchers.named("org.springframework.boot.SpringApplication"))
.transform(new SpringApplicationTransformer())
.installOn(inst);
}

和一个变压器:

@Override
public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module) {
try {
builder = builder
.defineMethod("run", classLoader.loadClass(
"org.springframework.context.ConfigurableApplicationContext"),
Modifier.PUBLIC | Modifier.STATIC)
.withParameter(Class.class).withParameter(String[].class)
.intercept(MethodCall
.invoke(named("run").and(isStatic()
.and(takesArguments(Object.class, String[].class))))
.withAllArguments());
return builder;
}
catch (Exception e) {
throw new IllegalStateException(e);
}
}

我可以在调试器中看到转换器被调用并成功完成,但我仍然无法调用该方法:

$ java -javaagent:target/spring-boot-legacy-agent-0.0.1-SNAPSHOT-agent.jar -jar target/spring-boot-legacy-agent-0.0.1-SNAPSHOT.jar --thin.profile=old
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.wrapper.ThinJarWrapper.launch(ThinJarWrapper.java:118)
at org.springframework.boot.loader.wrapper.ThinJarWrapper.main(ThinJarWrapper.java:90)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.thin.ThinJarLauncher.launch(ThinJarLauncher.java:186)
at org.springframework.boot.loader.thin.ThinJarLauncher.main(ThinJarLauncher.java:133)
... 6 more
Caused by: java.lang.NoSuchMethodError: org.springframework.boot.SpringApplication.run(Ljava/lang/Class;[Ljava/lang/String;)Lorg/springframework/context/ConfigurableApplicationContext;
at com.example.AgentApplication.main(AgentApplication.java:10)
... 15 more

将监听器添加到代理构建器可以获得更多信息:

ava.lang.IllegalStateException: class org.springframework.boot.SpringApplication does not define exactly one virtual method for (name(equals(run)) and hasParameter(hasTypes(erasures(containing(is(class java.lang.Object;), is(class [Ljava.lang.String;))))))
at net.bytebuddy.implementation.MethodCall$MethodLocator$ForElementMatcher.resolve(MethodCall.java:668)
at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:2002)
...

所以看起来方法匹配器不匹配。 具有这些参数类型的静态方法,但在过滤时它不在列表中。我一定是缺少静态方法的东西吗?

我确实设法让它与 javassist 一起工作,但我想了解为什么 byte-buddy 不工作。

最佳答案

匹配器 API 仅用于动态检测虚拟调用,其中这种类型相关检测可能有意义,主要是由于泛型。对于静态方法,您确实知道声明方法的确切类型以及方法的类型,因此您应该提供对静态方法的引用:

MethodCall.invoke(typeDescription
.getDeclaredMethods()
.filter(named("run")
.and(isStatic()
.and(takesArguments(Object.class, String[].class)))
.getOnly()).withAllArguments())

您使用的方法的 javadoc 中也提到了这一点:

Invokes a unique virtual method of the instrumented type that is matched by the specified matcher.

不过,我应该提供更多关于为什么以这种方式构建 API 的背景知识。

关于java - 将静态方法添加到类并委托(delegate)给现有方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49956509/

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