In my project I'm using the observer pattern in several places, i.e. the subject notifies the observers about something, and expect them to act. The subject does not know anything about the details of these observers.
With Spring I autowired/injected the observers as follows (constructor injection):
@Autowired public Subject(List<Observer> observers) {...}
This works, and as Observer
is an interface, there's no compile-time dependency from Subject
to Observer
. However, there needs to be a runtime dependency, so that the observers can be notified by the subject.
With the approach shown above, I experienced bean dependency cycle issues, as one of the observer's transitive dependencies was the subject itself.
To fix this, I introduced a new class SubjectInitializer
(and changed the Subject
accordingly):
@Autowired
public SubjectInitializer(Subject subject, List<Observer> observers) {
subject.addObservers(observers);
}
This way I don't have any bean dependency cycle, as SubjectInitializer
is not the target of any dependency.
However, this fix seems weird to me:
- The observer pattern is used quite a lot, so I guess there's a lot of experience on how to use it with Spring. However, I didn't find anything helpful.
- The whole purpose of the
SubjectInitializer
is to initialize theSubject
, which only has to happen once. Creating a new bean (and having the singleton in memory?) seems over the top.
Is there a better way to autowire the observer instances?
@Inject
in JavaEE environments. And yes, each observer may be provided to multiple subjects:EmitsSomething
could be a concreteSubject
, andY implements ReceivesSomething, ReceivesSomethingElse
might be an observer for this subject that also observes notifications from another subject.