From Class.getDeclaredFields()
:
Returns an array of Field objects reflecting all the fieldsdeclared by the class or interface represented by this Class object. This includes public, protected, default(package) access, and private fields, but excludes inherited fields.
In your case, once you have a subclass-based proxy from cglib, the field will only exist in the superclass. Depending on your use case, you might want to collect all fields up in the inheritance chain that have you custom annotation.
Example code:
Collection<Field> fieldsWithAnnotation = new ArrayList<>();
Class<?> clazz = // your class
while(clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
DynamicReference dynamicRefrence = field.getAnnotation(DynamicReference.class);
if(dynamicRefrence != null)
fieldsWithAnnotation.add(field);
}
clazz = clazz.getSuperclass();
}
EDIT: This approach works to find the annotated field. However, doing field.set(proxyInstance, value)
will actually set the field in the proxy. This does not help you, as even though the proxy subclasses, it still uses delegation to forward method calls to a wrapped instance of your actual class. Since your goal is apparently to set the field in this wrapped instance, I would advise you to not use a custom field injection but rather setter injection. Your code would look roughly like this (untested):
// in TestService
private ITestProvider testProvider;
@DynamicReference
public void setTestProvider(ITestProvider testProvider) { ... }
// Getting the method
while(clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
DynamicReference dynamicRefrence = method.getAnnotation(DynamicReference.class);
if(dynamicRefrence != null)
methodsWithAnnotation.add(method);
}
clazz = clazz.getSuperclass();
}
// invoking it
method.invoke(proxyInstance, dependencyInstanceYouWantToSet);
The proxy should delegate the method call to your wrapped instance. Maybe you even want to make the method protected.
The alternative would be getting the callback-field of the proxy and setting the field on that instance, but the approach above seems much cleaner (some might say that magic field injection is evil and you should always use setter/constructor injection for a clean oop approach).
Edit 2: maybe you could also rethink if you want to actually reinvent the DI framework and leverage the underlying existing DI framework functionality. Using @Qualifier or some custom injection resolver comes to mind. See eg this tutorial