代码之家  ›  专栏  ›  技术社区  ›  Kevin Daly

如何向ByteBuddy中的类添加字段,并在方法拦截器中设置/获取该值

  •  3
  • Kevin Daly  · 技术社区  · 10 年前

    我正在使用byte buddy在Ignite之上构建一个ORM,我们需要向类中添加一个字段,然后在方法拦截器中访问它。。

    下面是一个例子,我向类中添加了一个字段

    final ByteBuddy buddy = new ByteBuddy();
    
    final Class<? extends TestDataEnh> clz =  buddy.subclass(TestDataEnh.class)
            .defineField("stringVal",String.class)
            .method(named("setFieldVal")).intercept(
                MethodDelegation.to(new SetterInterceptor())
        )
        .make()
        .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
        .getLoaded();
    
    final TestDataEnh enh = clz.newInstance();
    
    enh.getFieldVal();
    enh.setFieldVal();
    
    System.out.println(enh.getClass().getName());
    

    拦截器是这样的

    public class SetterInterceptor {
        @RuntimeType
        public  Object intercept() {
            System.out.println("Invoked method with: ");
            return null;
        }
    }
    

    那么如何将新字段的值输入拦截器,以便更改其值呢?(字符串值)

    提前谢谢

    1 回复  |  直到 10 年前
        1
  •  1
  •   Rafael Winterhalter    10 年前

    您可以使用 FieldProxy 按字段名称访问字段。您需要安装 FieldProxy.Binder 并在 MethodDdelegation 因为它需要一个自定义类型用于类型安全检测。这个 java文档 解释了如何做到这一点。或者,您可以使用 @This JVM在优化反射的使用方面非常有效。

    例如:

    interface FieldGetter {
      Object getValue();
    }
    
    interface FieldSetter {
      void setValue(Object value);
    }
    
    public class SetterInterceptor {
      @RuntimeType
      public  Object intercept(@FieldProxy("stringVal") FieldGetter accessor) {
        Object value = accessor.getValue();
        System.out.println("Invoked method with: " + value);
        return value;
      }
    }
    

    对于bean属性 字段代理 注释不需要显式名称,但可以从截获的getter或setter的名称中发现名称。

    安装方法如下:

    MethodDelegation.to(SetterInterceptor.class)
                    .appendParameterBinder(FieldProxy.Binder.install(FieldGetter.class, 
                                                                     FieldSetter.class));