2015-11-01 2 views
1

В следующем фрагменте кода я вызываю метод doStuff один раз на экземпляр Subclass. Однако он перехватывается дважды.Метод перехвачен дважды, хотя он был вызван один раз

Отметьте, что doStuff был определен в родительском классе SuperClass. Если doStuff был определен в SubClass, логика перехвата работала бы так, как ожидалось: только один перехват.

Я использую 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

Вы перехватывают вызов метода для каждого типа, то есть для обоих Subclass и SuperClass. Вам нужно дополнительно указать ваш перехватчик для того, какие методы перехватывать. В этом случае вы хотите только перехватывать методы, если они объявлены заданным типом.

Это прост в применении. Вместо builder.method(any()) вы должны перехватить builder.method(isDeclaredBy(td)). Таким образом, метод только перехватывается, если он объявлен перехваченным типом.

Наконец, я могу видеть из вашего исходного кода, что вы используете более старую версию Byte Buddy. Версия 0.7-rc6 работает стабильно, имеет дополнительные функции и исправляет несколько ошибок. (Однако некоторые API все еще необходимо изменить.)

+0

Этот фрагмент работает на 0.7-rc6, но я все еще могу использовать некоторые старые API. О, и btw онлайн-javadoc для 0.7-rc6 кажется сломанным: http://bytebuddy.net/javadoc/0.7-rc6/index.html – user3408654

+1

Метод агента Byte Buddy 'ByteBuddyAgent.installOnOpenJDK()' должен быть 'ByteBuddyAgent.install () ', поскольку он поддерживает J9 и любые платформы, совместимые с Java 9. Спасибо за подсказку к javadoc, была проблема с именами. Теперь это исправлено. –

Смежные вопросы