18

Am trying to create an object using an AOP framework which uses CGLIB to create proxy objects. Strangely enough, the "enhanced" proxy object is devoid of ANY annotations the previous class had!

Can anyone tell me how can I make CGLIB retain the annotations on the proxies it creates?

Cheers! Nirav

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
Nirav
  • 211
  • 2
  • 3
  • Does @Inherited annotation solved the problem ? If so, you may consider approving the answer. Thanks. – koders Feb 15 '15 at 20:08
  • `@Inherited` doesn't solve the problem (I tried it by myself). Personally I was using a Spring project and solved by using AnnotationUtils utility class, so you can see [here](https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java) how it works. – Alessio Sep 28 '16 at 16:43

4 Answers4

15

CGLIB creates subclasses of given classes to generate proxies. Annotations are not preserved in subclasses unless explicitly specified in annotation definition. @Inherited annotation is used for this purpose.

You can use this annotation in the annotations you define, and make them reachable in subclasses, as following:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
}
koders
  • 5,654
  • 1
  • 25
  • 20
5

This isn't an issue with "retaining" the annotations. CGLIB proxies are actually generated subclasses of the target object's class. These subclasses may not have annotations, but their superclass (i.e. your own class) will still have them. Any annotation-reflecting code you use needs to be able to look back up the class hierarchy to look for annotations.

skaffman
  • 398,947
  • 96
  • 818
  • 769
4

Cglib is not capable of retaining annotations without changing its internal implementation. This is however quite complicated and believe me I tried. My altered version I finally came up with was however so complicated that I decided to rather implement Byte Buddy, another code generation library which is capable of such functionality.

Here is an example of how you can create subclass that

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation { }

@MyAnnotation
class MyClass { }

assertThat(new ByteBuddy()
  .subclass(Object.class)
  .attribute(TypeAttributeAppender.ForSuperType.INSTANCE)
  .make()
  .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
  .getLoaded()
  .isAnnotationPresent(MyAnnotation.class), is(true));

Byte Buddy comes with an extensive full-text documentation and javadoc and it is quite extensible. Hope you make good use of the library.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
3

It's a valid problem (I'm running into now myself) as a) not all frameworks are smart enough to inspect parent classes b) even if they are smart enough, they may chose not to. The latter seems to be the case with Guice. FWIW, https://issues.apache.org/jira/browse/WICKET-1130 is the problem I was working on when I found this out.

Eelco
  • 1,718
  • 22
  • 16