I am currently working on an application which has interdependent services, injected via Spring Java Configuration classes, somewhat like this:
@Configuration public class ExampleConfiguration { @Bean public IFirstService firstService() { return new FirstServiceImpl(); } @Bean public ISecondService secondService() { return new SecondServiceImpl(); } } @Service public class FirstServiceImpl implements IFirstService{ ... } @Service public class SecondServiceImpl implements ISecondService{ @Inject private IFirstService firstService; ... } This is working as intended, with a single instance of each service created and injected throughout the application. However, I'm interested in converting to constructor injection - it seems like it would provide better support for unit/mock testing patterns. As I understand it, it would change the SecondServiceImpl code to something like this:
@Service public class SecondServiceImpl implements ISecondService { private IFirstService firstService; @Inject public SecondServiceImpl(IFirstService firstService){ this.firstService = firstService; } ... } The problem I'm running into is determining how this interacts/works with the Configuration class above. All the examples I've seen of this do something like:
@Configuration public class ExampleConfiguration { @Bean public IFirstService firstService() { return new FirstServiceImpl(); } @Bean public ISecondService secondService() { return new SecondServiceImpl(firstService()); } } But this seems like it would defeat the idea that there should be one instance of IFirstService injected throughout the application, since each call to firstService() instantiates a new IFirstService instance.
I don't know if I am missing a detail about how Spring handles such a thing, or going about dependency injection wrong. Any suggestions would be appreciated!
EDIT:
While the accepted answer is correct, I have recently discovered there is a more robust way to do this - you can specify the desired item as a parameter on the method annotated with @Bean, and it will be injected from the same or other available configurations. So the above would become:
@Configuration public class ExampleConfiguration { @Bean public IFirstService firstService() { return new FirstServiceImpl(); } @Bean public ISecondService secondService(IFirstService firstService) { return new SecondServiceImpl(firstService); } } Note that @Qualifier annotations can be used in-line with the member parameters if a particular bean id is needed