2016-07-22 32 views
1

ich ein Java-Agenten haben, wie dies umgesetzt:Intercept alle Methoden/construtors/Getter/Setter von einem bestimmten Namensraum

public static void premain(String args, Instrumentation instrumentation) throws ClassNotFoundException { 
    new AgentBuilder.Default() 
     .type(isSubTypeOf(Object.class).and(nameStartsWith("com.my.domain"))) 
     .transform(new Transformer5()) 
     .installOn(instrumentation); 
} 

und dann Transform-Klasse:

public class Transformer5 implements AgentBuilder.Transformer { 
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) { 
     return builder.method(any().and(isDeclaredBy(typeDescription))) 
         .intercept(MethodDelegation.to(Interc4.class)); 
    } 
} 

und ein intercepter:

public class Interc4 { 

    static String indent = ""; 

    @RuntimeType 
    @BindingPriority(BindingPriority.DEFAULT * 3) 
    public static Object intercept(@SuperCall Callable<?> zuper, 
            @AllArguments Object[] allArguments, 
            @Origin String method) throws Exception { 

     System.out.println(indent + "Intercepted4 M" + method); 

     try { 
      indent += " "; 
      return zuper.call(); 
     } finally { 
      //post process 
      indent = indent.substring(0, indent.length()-2); 
     } 

    } 

} 

Das Problem damit ist, dass es Konstruktoren nicht abfängt, und es gibt auch diese Art von Fehler s

nicht nicht-öffentliche oder nicht-virtuelle Methode ‚lambda $ statischer $ 1‘ für die Schnittstelle

Typen

Was ist der beste Weg, Abfangjäger zu machen definieren ist, dass von einigen Proxy jede Methode in einer Klasse Domäne (Ich möchte in der Lage sein, Methodenname zu erhalten, Methodenargumente zu prüfen (falls vorhanden) und nur mit der Ausführung weiterleiten).

Antwort

1

Es gibt zwei Gründe für das, was passiert.

  1. Cannot define non-public or non-virtual method 'lambda$static$1' for interface type wird durch einen Überprüfungsfehler in Byte Buddy verursacht. Ich werde das für die nächste Version beheben. In der Zwischenzeit können Sie die Validierung durch new AgentBuilder.Default(new ByteBuddy().with(TypeValidation.DISABLED)) deaktivieren.

  2. Sie können Methoden nur abfangen, indem Sie über .method(...) abgleichen. Sie können Konstruktoren abfangen, indem Sie .constructor(...) oder eine beliebige durch .invokable(...) aufrufen. Sie können Ihren Interceptor jedoch nicht für Konstruktoren verwenden, bei denen der Supermethodenaufruf fest codiert sein muss. Sie können Ihre Abfangjäger in zwei Bits jedoch aufgeteilt:

    class Interceptor { 
        public static void before() { ... } 
        public static void after() { ... } 
    } 
    

    .intercept(MethodDelegation.to(Interceptor.class).filter(named("before") 
        .andThen(SuperMethodCall.INSTANCE 
        .andThen(MethodDelegation.to(Interceptor.class).filter(named("after")))) 
    

Auf diese Weise verwenden, Byte Buddy kann hart-Code der Super-Konstruktor Aufruf und noch lösen die before und after Methoden. Beachten Sie, dass die Annotation @This für die Methode before nicht verfügbar ist.