2016-01-13 2 views
4

Byte Buddy, по-видимому, оценивает публичные классы как реализации перехватчиков, даже если я предоставляю фактический экземпляр; часто я ловлю себя на желании сделать что-то вроде этого:Видимость класса перехватчика в Byte Buddy

import static MethodDelegation.to; 

new ByteBuddy().subclass(Object.class).method(any()).intercept(to(new Object() { 
    @RuntimeType 
    public Object intercept(@Origin Method m, @AllArguments Object[] a) { 
    return null; 
    } 
}); 

который, однако, приводит к исключению следующим образом:

Exception in thread "main" java.lang.IllegalStateException: class net.bytebuddy.renamed.java.lang.Object$ByteBuddy$pUmdGhyP cannot access class us.levk.guice.vs.Scopes$1Builder$1 

Есть ли причина видимости исполнения?

EDIT: У меня все еще есть проблемы с этим; Я получаю другое исключение, это мой код:

package us.levk.guice.vs; 

import static net.bytebuddy.implementation.MethodDelegation.to; 
import static net.bytebuddy.matcher.ElementMatchers.any; 

import java.lang.reflect.Method; 
import java.util.function.Function; 
import java.util.function.Supplier; 

import net.bytebuddy.ByteBuddy; 
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; 
import net.bytebuddy.implementation.bind.annotation.AllArguments; 
import net.bytebuddy.implementation.bind.annotation.Origin; 
import net.bytebuddy.implementation.bind.annotation.RuntimeType; 

public class Bar { 

    Function<Supplier<?>, Class<?>> wrapper() { 
    return s -> { 
     return new ByteBuddy().subclass (Object.class) 
          .name (Bar.class.getPackage().getName() + ".Foo") 
          .method (any()) 
          .intercept (to (new Object() { 
           @RuntimeType 
           public Object intercept (@Origin Method method, 
                 @AllArguments Object[] args) { 
           System.out.println (method); 
           return null; 
           } 
          })) 
          .make() 
          .load (getClass().getClassLoader(), 
            ClassLoadingStrategy.Default.WRAPPER) 
          .getLoaded(); 
    }; 
    } 

    public static void main (String[] args) throws InstantiationException, IllegalAccessException { 
    new Bar().wrapper().apply (() -> new Integer (1)).newInstance().toString(); 
    } 
} 

И исключение теперь:

Exception in thread "main" java.lang.IllegalAccessError: tried to access class us.levk.guice.vs.Bar$1 from class us.levk.guice.vs.Foo 

EDIT2:

Он отлично работает, если я меняю стратегию загрузки классов инъекции

ответ

1

В этом случае Byte Buddy сообщает вам о ограничении видимости, которое вызовет IllegalAccessException во время выполнения.

Если вы заявляете свой метод public, анонимный класс автоматически определяется как приватный к javac. Следовательно, метод не отображается для сгенерированного класса, так как net.bytebuddy.renamed.java.lang.Object не равен us.levk.guice.vs.Scopes.

Если вы сделали:

new ByteBuddy().subclass(Object.class).name("us.levk.guice.vs.Foo") 
       .method(any()).intercept(to(new Object() { 
    @RuntimeType 
    public Object intercept(@Origin Method m, @AllArguments Object[] a) { 
    return null; 
    } 
})); 

все будет работать. В качестве альтернативы вы можете определить, например, открытый интерфейс, такой как:

public interface Foo { 
    @RuntimeType 
    Object intercept(@Origin Method m, @AllArguments Object[] a); 
} 

new ByteBuddy().subclass(Object.class).name("us.levk.guice.vs.Foo") 
       .method(any()).intercept(to(new Foo() { 
    @RuntimeType 
    public Object intercept(@Origin Method m, @AllArguments Object[] a) { 
    return null; 
    } 
}, Foo.class)); 
Смежные вопросы