簡體   English   中英

將靜態方法添加到類並委托給現有方法

[英]Add a static method to class and delegate to an existing method

這就是我所擁有的。 代理商:

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一起使用,但是我想了解為什么字節伙伴無法正常工作。

Matcher API僅用於動態檢測虛擬調用,在這種情況下,這種類型相關的檢測有意義(主要是由於泛型)。 但是,對於靜態方法,您確實知道聲明方法的確切類型以及該方法的類型,因此應改為提供對靜態方法的引用:

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

您正在使用的方法的javadoc中也提到了這一點:

調用與指定匹配器匹配的檢測類型的唯一虛擬方法。

但是,我應該提供更多有關為何以這種方式構建API的背景知識。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM