I'm attempting to create a number of classes at runtime using ByteBuddy. So far I've managed to create the classes, add methods and annotate them. It's a great tool and I've enjoyed using it so far.
But now I'm stuck. I have my class, with a method and there are n number of parameters (dynamically controlled by config). This works something like...
DynamicType.Builder<?> builder = new ByteBuddy().subclass(Object.class)
.name(newClassName)
.annotateType(AnnotationDescription.Builder.ofType(Controller.class).build());
// loop for all methods to create
for (final MethodDefinition methodDefinition : methodDefinitions) {
final List<TypeDefinition> parameters = new ArrayList<>();
for (final MethodParameterDefinition methodParamDef : methodDefinition.getMethodParameterDefinitions()) {
parameters.add( TypeDescription.Generic.Builder.rawType(methodParamDef.getType()).build() );
}
// define the method
builder = builder
.defineMethod(methodDefinition.getName(), outputValueObjectClass, Modifier.PUBLIC)
.withParameters(parameters)
.annotateMethod(AnnotationDescription.Builder.ofType(RequestMapping.class)
.defineEnumerationArray("method", RequestMethod.class, RequestMethod.valueOf(methodDefinition.getHttpMethod()))
.defineArray("path", methodDefinition.getUrl()).build())
.annotateMethod(AnnotationDescription.Builder.ofType(ResponseBody.class).build())
}
final DynamicType.Unloaded unloadedClass = builder.make();
But when I attempt to add an annotation to one of the parameters by using the following code...
for (final MethodParameterDefinition methodParamDef : methodDefinition.getMethodParameterDefinitions()) {
parameters.add( TypeDescription.Generic.Builder.rawType(methodParamDef.getType())
.annotate(AnnotationDescription.Builder.ofType(PathVariable.class).define("name", methodParamDef.getName()).build())
.build() );
}
...I get the following exception....
java.lang.IllegalStateException: Illegal type annotations return type class...
If I know the number of method parameters I can add these using code like...
builder = builder
.defineMethod(methodDefinition.getName(), outputValueObjectClass, Modifier.PUBLIC)
.withParameter(methodParameterClass).annotateParameter(AnnotationDescription.Builder.ofType(ModelAttribute.class).build())
.annotateMethod(AnnotationDescription.Builder.ofType(RequestMapping.class)
.defineEnumerationArray("method", RequestMethod.class, RequestMethod.valueOf(methodDefinition.getHttpMethod()))
.defineArray("path", methodDefinition.getUrl()).build())
.annotateMethod(AnnotationDescription.Builder.ofType(ResponseBody.class).build())
But this doesn't work for a dynamic approach.
Does anyone know how to add a dynamic number of parameters (with annotations) to a method?
Thanks in advance!
I just checked the code and the exception message is misleading due to a copy-paste error. The error message should tell you that you are annotating a type with an annotation that is not a type annotation.
Note the difference between the annotation
and the annotateParameter
in the code generation DSL. The former annotates the type, the other one the parameter. This might seem confusing as the syntax is ambigous:
void foo(@Bar List<?> qux) { ... }
can mean both in Java, if @Bar
is a type annotation, it annotates the List
type, if it is a parameter annotation, it annotates the parameter qux
, if it is both, the type and the parameter will be annotated. On the byte code level, you can choose what element to annotate. But since your annotation is only compatible to parameters, the (misleading, this is now fixed on master) error message is shown.
If you want to add a dynamic number of parameters, just run the loop on the DynamicType.Builder
and add the parameters like this:
MethodDefinition.ParameterDefinition builder = ...
for (...) {
builder = builder.withParameter(...).annotateParameter(...);
}
This should do the trick.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.