简体   繁体   English

Byte Buddy中的拦截器类可见性

[英]Interceptor class visibility in Byte Buddy

Byte Buddy seems to only appreciate public classes as interceptor implementations even if I provide the actual instance; Byte Buddy似乎只是喜欢公共类作为拦截器实现,即使我提供了实际的实例; frequently I find myself wanting to do something like this: 经常我发现自己想做这样的事情:

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;
  }
});

Which however results in an exception as follows: 但是会产生如下异常:

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

Is there any reason behind visibility enforcement? 能见度执法背后有什么理由吗?

EDIT: I'm still having trouble with it though; 编辑:我仍然遇到麻烦; I'm getting a different exception, this is my code: 我得到了一个不同的例外,这是我的代码:

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 ();
  }
}

And the exception is now: 现在例外是:

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: EDIT2:

It works fine if I change the classloading strategy to INJECTION 如果我将类加载策略更改为INJECTION,它可以正常工作

In this case, Byte Buddy informs you about a visibility constraint that would cause an IllegalAccessException at runtime. 在这种情况下,Byte Buddy会通知您有关在运行时会导致IllegalAccessException的可见性约束。

Eventhough you declare your method public , the anonymous class is automatically defined to be package private by javac . 虽然你声明你的方法是public ,但是匿名类被javac自动定义为包私有。 Therefore, the method is not visible to the generated class since net.bytebuddy.renamed.java.lang.Object is not equal to us.levk.guice.vs.Scopes . 因此,该方法对生成的类是不可见的,因为net.bytebuddy.renamed.java.lang.Object不等于us.levk.guice.vs.Scopes

If you did: 如果你这样做:

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;
  }
}));

everything would work. 一切都会奏效。 Alternatively, you can define - for example - a public interface such as: 或者,您可以定义 - 例如 - 公共接口,例如:

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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM