0

I have a class with default visibility without any explicit constructors. i want to generate similar class (with same methods and annotations) but with explicit public default constructor. is it possible in easy way? any ready to use proxy frameworks? i'm afraid that doing it manually with cglib will be rather big task

piotrek
  • 13,982
  • 13
  • 79
  • 165

1 Answers1

1

cglib will always override methods without copying annotations. There is no support for annotations in cglib as it was written before Java 5 came out.

If you are open to using a different library than cglib, have a look at my library Byte Buddy for defining such constructors. Using it, you can either define a Java agent for increasing the original class's visibility or you can create a subclass where you instruct retaining libraries.

A subclass would be generated somewhat as follows:

DynamicType.Builder<? extends Foo> builder = new ByteBuddy()
  .subclass(Foo.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
  .modifiers(() -> return Foo.class.getModifiers() | Modifiers.PUBLIC);
Foo.class.getDeclaredConstructors().forEach( c ->
  DynamicType.Builder.MethodAnnotationTarget<? extends Foo> target = builder
      .defineConstructor(Arrays.asList(c.getParamaterTypes), 
                         () -> return c.getModifiers() | Modifiers.PUBLIC)
      .intercept(SuperMethodCall.INSTANCE)
      .annotateMethod(c.getAnnotations());
  int index = 0;
  for(Annotation[] a : c.getParameterAnnotatations()) {
    target = target.annotateParameter(index++, a);
  }
  builder = target;
)
Class<? extends Foo> subclass = builder.make()
  .load(Foo.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER);

This looks like a lot of code at first (I am currently enhancing the API to make this much shorter. What you however do is the following:

  1. You define a new subclass of Foo and instruct Byte Buddy not to add any constructors.
  2. You define the modifiers of this class to resemble those of Foo but additionally be public.
  3. You look up all constructors that Foo declares and for each such constructor, you define a new constructor for the generated subclass. This constructor defines the exact same parameter types as the constructor of Foo and also copies the modifiers. Additionally, the visibility is however set to become public.
  4. You copy all annotations of Foo's constructor to become present on the subclass's constructor.
  5. You repeat this for all parameter annotations.
  6. You make and load the class (on Foo's class loader).
Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192