Byte Buddy is a library for the runtime generation of Java classes. Its capabilities are not limited to the creation of proxy classes but the creation of proxy classes is an obvious use case.
Assuming, we are dealing with the following code:
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation { }
@MyAnnotation
class Foo {
@MyAnnotation
public void bar() { }
}
Then we can create a subclass at runtime that overrides the bar
method. The overridden implementation of the bar
method is implemented to simply call its super implementation:
Class<?> runtimeType = new ByteBuddy()
.withAttribute(TypeAttributeAppender.ForSuperType.INSTANCE)
.withDefaultMethodAttributeAppender(MethodAttributeAppender.ForInstrumentedMethod.INSTANCE)
.subclass(Foo.class)
.method(named("bar")).intercept(SuperMethodCall.INSTANCE)
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
With the above runtime class, we can now verify the resulting type:
assertNotEquals(Foo.class, runtimeType);
assertThat(runtimeType.isAnnotationPresent(MyAnnotation.class)), is(true));
assertThat(runtimeType.getDeclaredMethod("bar").isAnnotationPresent(MyAnnotation.class)), is(true));
Both the type and the method are annotated by MyAnnotation
despite the subclass. By calling getDeclaredMethod
, we furthermore verify that the subclass actually defines a new method.
Disclosure: I am the author of Byte Buddy and I wanted to provide an answer to this question that is often asked on SO in a slightly more specific context. Furthermore, I wanted to take the opportunity to create a SO tag for Byte Buddy.