Reputation: 21113
I am presently trying to implement wrapping a java.util.Map
of key/value pairs using ByteBuddy as a java bean that exposes the map keys as normal getter/setters.
I initially construct the builder as follows allowing me to pass the Map
as a constructor argument:
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 ) ) );
What I am not sure about is how to define the associated getter/setter methods so they effectively replicate this behavior:
public Integer getFoo() {
return theMap.get( "foo" );
}
public void setFoo(Integer foo) {
theMap.put( "foo", foo );
}
I understand from ByteBuddy that I effectively would do something similar to this:
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 */ );
The question is what goes inside the intercept method call ?
Upvotes: 1
Views: 1030
Reputation: 21113
I ended up doing it this way
// 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 ) ) );
In both cases, it was simply the need to delegate a MethodCall#invoke
to the appropriate Map
method I was trying to encapsulate using the appropriate map key.
Also in the case of the set method, it was important to delegate the incoming argument 0, the provided setter method's argument to the map method invocation with the key.
Upvotes: 2