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)?
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
.