我目前正在尝试使用ByteBuddy将java.util.Map
键/值对包装为java bean,将地图键公开为普通的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 */ );
问题是拦截方法调用内部是什么?
答案 0 :(得分: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方法调用。