Reputation: 127
In my Spring Boot app, I have events that should be reported in various ways, depending on the environment.
I defined interface IReporter
and several implementations, namely LogReporter
, EmailReporter
, RpcReporter
. Also new implementations may appear in future.
Now I want my events to be reported using a subset of reporters. The subset must be specified in the app configuration as the following (for example):
events.reporters=LogReporter,EmailReporter
or
events.reporters=${EVENT_REPORTERS}
or something similar.
As a result, I would like the component that handles events (say class EventHandler
) to have magically injected List<IReporter> myReporters
containing only the necessary implementations.
And, of course, if a new implementation is created, the only thing to update must be the app configuration (not the code of EventHandler
).
I'm familiar with injecting all available implementations, only a @Primary
implementation, or a specific one picked with @Qualifier
. But looks like these do not solve my problem.
Upvotes: 0
Views: 543
Reputation: 1650
class EventHandler {
@Value("${events.reporter}")
List<String> requiredImplementation;
@Autowired
List<IReporter> myReporters;
public List<IReporter> getRequiredImplementation() {
return myReporters.stream()
.filter(reporter -> requiredImplementation.contains(reporter.getClass().getSimpleName()))
.collect(Collectors.toList());
}
}
EDIT: One option I could think if we want framework to autowire only the required beans, we can explore @ConditionalOnExpression.
For instance:
@Component
@ConditionalOnExpression("#{'${events.reporter}'.contains('LogReporter')}")
Class LogReporter {
}
@Component
@ConditionalOnExpression("#{'${events.reporter}'.contains('EmailReporter')}")
Class EmailReporter {
}
Upvotes: 1