4

I've been using Spring for decades, but never ran into this use-case before.

Is there a way to inject all the beans annotated with a specific annotation, e.g. all beans with @Service or all with @CustomAnnotation?

The only idea I have is to inject the context, get all the beans and filter manually. If this is the only way, does Spring expose a method that recursively scans a class hierarchy for (meta) annotations (as most Spring annotations can be used as meta-annotations)?

kaqqao
  • 12,984
  • 10
  • 64
  • 118

1 Answers1

5

The @ComponentScan annotation specifies includeFilters and excludeFilters attributes.
To scan only classes decorated with @Service you could disable useDefaultFilters and include only the Service annotation :

@ComponentScan(useDefaultFilters = false,
                includeFilters = @Filter(Service.class))

To scan only custom annotations, you could write a similary thing :

@ComponentScan(useDefaultFilters = false,
                includeFilters = @Filter(CustomAnnotation.class))

As multiples classes are specified in value/classes of @Filter, a OR logic is applied.


Note that the @Filter annotation accepts class(es) as value/classes attribute but these are interpreted by Spring according to the type value of @Filter.
By default, type has as value FilterType.ANNOTATION.
To filter on a specific annotation (as you in your case), this default value suits as you want to filter candidates on the annotation itself.

Here values defined in the FilterType enum class :

public enum FilterType {     
    ANNOTATION,    
    ASSIGNABLE_TYPE,
    ASPECTJ,
    REGEX,
    CUSTOM    
}

Note also that @Filter works with classes/value but not only.
You have indeed two alternative ways :

  • valuing the classes/value attribute (as in your case)

  • valuing pattern attribute.

The first way expects to have as type : ANNOTATION, ASSIGNABLE_TYPE or CUSTOM.
While the second way expects to have as type : REGEX or ASPECTJ.

davidxxx
  • 125,838
  • 23
  • 214
  • 215