如何使用ByteBuddy添加自定义get / set方法

问题描述 投票:1回答:1

我目前正在尝试使用ByteBuddy作为一个java bean来实现包装密钥/值对的java.util.Map,它将map键公开为普通的getter / setter。

我最初构建构建器如下允许我传递Map作为构造函数参数:

DynamicType.Builder builder = new ByteBuddy()
  .subclass( Object.class )
  .name( customClassName )
  .implement( Serializable.class )
  .defineField( "theMap", Map.class )
  .defineConstructor( Modifier.PUBLIC )
    .withParameters( Map.class )
    .intercept(
      MethodCall.invoke( Object.class.getConstructor() ).onSuper()
        .andThen( FieldAccessor.ofField( "theMap" ).setArgumentAt( 0 ) ) );

我不确定的是如何定义相关的getter / setter方法,以便它们有效地复制此行为:

public Integer getFoo() {
  return theMap.get( "foo" );
}

public void setFoo(Integer foo) {
  theMap.put( "foo", foo );
}

我从ByteBuddy那里了解到,我实际上会做类似的事情:

builder.defineMethod( "getFoo", Integer.class, Modifier.PUBLIC )
  .intercept( /* what goes here */ );

builder.defineMethod( "setFoo", Void.clss, Modifier.PUBLIC )
  .withParameters( Integer.class )
  .intercept( /* what goes here */ );

问题是截取方法调用内部的内容是什么?

java byte-buddy
1个回答
2
投票

我最终这样做了

// The Getter
builder = builder.defineMethod( "getFoo", Integer.class, Modifier.PUBLIC )
  .intercept(
    MethodCall.invoke( Map.class.getMethod( "get", Object.class ) )
      .onField( "theMap" )
      .with( propertyKey ) );

// The Setter
builder = builder.defineMethod( "setFoo", void.class, Modifier.PUBLIC )
  .withParameters( Integer.class )
  .intercept(
    MethodCall.invoke( Map.class.getMethod( "put", Object.class, Object.class ) )
      .onField( "theMap" )
      .with( propertyKey ) )
      .withArgument( 0 )
      .andThen( new Implementation.Simple( MethodReturn.VOID ) ) );

在这两种情况下,只需要将MethodCall#invoke委托给我试图使用适当的映射键封装的适当的Map方法。

同样在set方法的情况下,重要的是将传入的参数0,提供的setter方法的参数委托给使用键的map方法调用。

© www.soinside.com 2019 - 2024. All rights reserved.