NikS
NikS

Reputation: 127

Spring Boot: how to configure a set of implementations to inject?

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

Answers (1)

Kumar V
Kumar V

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

Related Questions