Reputation: 31
How can I define a method and then decorate it (multiple times) with ByteBuddy ? This is my example
Builder<Object> builder = new ByteBuddy().subclass(Object.class).name("Dynamic");
builder = builder.defineMethod("method", void.class, Visibility.PUBLIC)
.intercept(MethodDelegation.to(new Object(){
@RuntimeType
public void intercept(@This Object o) {
System.out.println("Executing code...");
}
}));
builder = builder.method(ElementMatchers.named("method")).
intercept(MethodDelegation.to(new Object(){
@RuntimeType
public void intercept(@This Object o) {
System.out.println("Executing other code...");
}
}));
try {
Class cls = builder.make()
.load(StructClassBuilder.class.getClassLoader())
.getLoaded();
Object obj = cls.newInstance();
cls.getDeclaredMethod("method").invoke(obj, args);
} catch (Exception e1) {
e1.printStackTrace();
}
The output is
Executing other code...
I would like that the output is
Executing code...
Executing other code...
Thanks
Upvotes: 1
Views: 1177
Reputation: 1608
One option is to chain Your interceptors using MethodDelegation.to(...).addThen(...) methods.
public class ByteBuddyTest {
public static void main(String[] args) throws Exception {
DynamicType.Builder<Object> builder = new ByteBuddy().subclass(Object.class).name("Dynamic");
builder = builder
.defineMethod("method", void.class, Visibility.PUBLIC)
.intercept(MethodDelegation.to(Interceptor1.class).andThen(MethodDelegation.to(Interceptor2.class)));
try {
Class<?> clazz = builder.make().include().load(ByteBuddyTest.class.getClassLoader()).getLoaded();
Object obj = clazz.newInstance();
clazz.getDeclaredMethod("method").invoke(obj, args);
} catch (Exception e1) {
e1.printStackTrace();
}
}
public static class Interceptor1 {
public static void intercept() {
System.out.println("Executing code...");
}
}
public static class Interceptor2 {
public static void intercept() {
System.out.println("Executing other code...");
}
}
}
Upvotes: 1
Reputation: 31
I'll use decorator pattern to decorate the Interceptor, now it works as expected. I share my solution:
private static interface Interceptor{
public void intercept(@This Object o);
}
private abstract static class InterceptorDecorator implements Interceptor{
protected Interceptor interceptor;
public InterceptorDecorator(Interceptor interceptor){
this.interceptor = interceptor;
}
public void intercept(@This Object o) {
if(interceptor!=null){
interceptor.intercept(o);
}
}
}
private static class Interceptor1 extends InterceptorDecorator{
public Interceptor1(Interceptor interceptor) {
super(interceptor);
}
public void intercept(@This Object o) {
super.intercept(o);
System.out.println("Executing code...");
}
}
private static class Interceptor2 extends InterceptorDecorator{
public Interceptor2(Interceptor interceptor) {
super(interceptor);
}
public void intercept(@This Object o) {
super.intercept(o);
System.out.println("Executing other code...");
}
}
public static void main(String[] args) {
Interceptor interceptor = new Interceptor1(null);
interceptor = new Interceptor2(interceptor);
Builder<Object> builder = new ByteBuddy().subclass(Object.class).name("Dynamic");
builder = builder.defineMethod("method", void.class, Visibility.PUBLIC)
.intercept(MethodDelegation.to(interceptor));
try {
Class cls = builder.make()
.load(StructClassBuilder.class.getClassLoader())
.getLoaded();
Object obj = cls.newInstance();
cls.getDeclaredMethod("method").invoke(obj, args);
} catch (Exception e1) {
e1.printStackTrace();
}
}
Upvotes: 0