1

With Spring, you can have some kind of composed annotations. A prominent example is the @SpringBootApplication-annotation, which is a composite of an @Configuration, @EnableAutoConfiguration and @ComponentScan.

I am trying to get all Beans that are affected by a certain annotation, i.e. ComponentScan.

Following this answer, I am using the following code:

for (T o : applicationContext.getBeansWithAnnotation(ComponentScan.class).values()) {
    ComponentScan ann = (ComponentScan) o.getClass().getAnnotation(ComponentScan.class);
    ...
}

which does not work, since not all beans, returned by getBeansWithAnnotation(ComponentScan.class) are indeed annotated with that annotation, since those that are e.g. annotated with @SpringBootApplication are (usually) not.

Now I am looking for some kind of generic way, to retrieve the value of an annotation, even when it is only added as piece of another annotation. How can I do this?

2 Answers2

2

It turns out, there is a utility set AnnotatedElementUtils which allows you to handle those merged annotations.

for (Object annotated : context.getBeansWithAnnotation(ComponentScan.class).values()) {
    Class clazz = ClassUtils.getUserClass(annotated) // thank you jin!
    ComponentScan mergedAnnotation = AnnotatedElementUtils.getMergedAnnotation(clazz, ComponentScan.class);
    if (mergedAnnotation != null) { // For some reasons, this might still be null.
        // TODO: useful stuff.
    }
}
1

it may be CglibProxy. so you can not directly get the Annotation.

ClassUtils.isCglibProxyClass(o)

for more see this


edit,you can add your logic code. find the ComponentScan.

if (ClassUtils.isCglibProxyClass(o.getClass())) {
            Annotation[] annotations = ClassUtils.getUserClass(o).getAnnotations();
            for (Annotation annotation : annotations) {
                ComponentScan annotation1 = annotation.annotationType().getAnnotation(ComponentScan.class);
// in my test code , ComponentScan can get here.for @SpringBootApplication 
                System.out.println(annotation1);
            }

        }
jin
  • 430
  • 2
  • 9
  • Your guess is right, it is a CglibProxyClass. But the annotation `ComponentScan` is also not present at the `ClassUtils.getUserClass(o)` - `@SpringBootApplication` is present for both classes, `ClassUtils.getUserClass(o)` and `o.getClass()` – derM - not here for BOT dreams May 27 '19 at 15:57
  • I believe you have 2 choices, #1 know all the Annotations annotated with ComponentScan. From your initial knowledge, SpringBootApplication is one. So if you found that the class is annotated with, and the rest of composed annotations (hopefully spring has document), then you know that the class has ComponentScan using the 'hardcoded' list of annotations. Another way is to (#2) find the ComponentScan annotation of the annotation that is not ComponentScan. As example, this is true: SpringBootApplication.class.isAnnotationPresent(ComponentScan.class) – Jayr May 27 '19 at 16:42
  • @jin, so you basically suggest, to crawl recursively through the tree, composing the annotations to find the one I am looking for. This seems to work, but I cannot retrieve the associated value, yet. However it points in the right direction, just beeing a bit more complicated. It seems, the values are not really set, so I have to check for the *annotations methods, annotated with `AliasFor.class`* to find which values I have to read. – derM - not here for BOT dreams May 27 '19 at 16:58
  • yes,it is complicate.another way i want to get some information exist in BeanDefinition.but it also complicate. – jin May 28 '19 at 01:13