2015-11-01 102 views
1

在下面的代碼片段中,我將調用方法doStuff一次在Subclass的實例上。但它被截獲兩次。即使被調用一次,方法也會截獲兩次

請注意,doStuff是在父類SuperClass中定義的。如果doStuff在​​中定義,則攔截邏輯將按預期工作:只有一個攔截。

我是否錯誤地使用了Byte Buddy?

package com.test; 

import static net.bytebuddy.matcher.ElementMatchers.any; 
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; 

import java.util.concurrent.Callable; 

import net.bytebuddy.agent.ByteBuddyAgent; 
import net.bytebuddy.agent.builder.AgentBuilder; 
import net.bytebuddy.description.type.TypeDescription; 
import net.bytebuddy.dynamic.DynamicType.Builder; 
import net.bytebuddy.implementation.MethodDelegation; 
import net.bytebuddy.implementation.bind.annotation.RuntimeType; 
import net.bytebuddy.implementation.bind.annotation.SuperCall; 

import org.junit.Test; 

public class ReproBugTest { 

    @Test 
    public void reproBug() { 

     new AgentBuilder.Default().type(nameStartsWith("com.test")) 
            .transform(new AgentBuilder.Transformer() { 

             @Override 
             public Builder<?> transform(
               Builder<?> builder, 
               TypeDescription td) { 

              return builder.method(any()) 
                  .intercept(
                    MethodDelegation.to(MethodInterceptor.class)); 
             } 
            }) 
            .installOn(
              ByteBuddyAgent.installOnOpenJDK()); 

     SubClass subClass = new SubClass(); 
     subClass.doStuff(); 
    } 
} 

class SuperClass { 
    public void doStuff() { 
     System.out.println("Doing stuff..."); 
    } 
} 

class SubClass extends SuperClass { 
} 

class MethodInterceptor { 

    @RuntimeType 
    public static Object intercept(@SuperCall Callable<?> zuper) 
      throws Exception { 

     // Intercepted twice, bug? 
     System.out.println("Intercepted"); 

     Object returnValue = zuper.call(); 

     return returnValue; 
    } 
} 

回答

1

您攔截方法調用每一個類型的,即兩個SubclassSuperClass。您需要進一步指定攔截器攔截哪些方法。在你的情況下,你只想攔截方法,如果它們是由給定類型聲明的。

這很容易實現。而不是builder.method(any()),你應該攔截builder.method(isDeclaredBy(td))。這樣,只有在攔截類型聲明的方法中才攔截該方法。

最後,我可以看到,您的源代碼中使用了舊版本的Byte Buddy。版本0.7-rc6運行穩定,具有附加功能並修復了一些錯誤。 (然而,一些API仍然需要改變。)

+0

這段代碼運行在0.7-rc6上,但我仍然可能會使用一些舊的API。哦,順便說一句,0.7-rc6的在線javadoc似乎打破了:http://bytebuddy.net/javadoc/0.7-rc6/index.html – user3408654

+1

Byte Buddy代理方法'ByteBuddyAgent.installOnOpenJDK()'應該是ByteBuddyAgent.install ),因爲它支持J9和任何Java 9兼容平臺。感謝提供給javadoc的提示,是一個命名問題。現在已經修復了。 –

相關問題