Is it possible to have a Spring Bean implement 2 interfaces and be able to autowire that bean using either interface?
I have the following two interfaces:
public interface ServiceA {}
public interface ServiceB {}
Two controllers which use constructor auto-wiring to inject a different service:
@RestController
public class ControllerA {
public ControllerA(ServiceA service) {}
}
@RestController
public class ControllerB {
public ControllerB(ServiceB service) {}
}
One class that implements both the services
@Service
public class ServiceImpl implements ServiceA, ServiceB { }
I am getting a NoSuchBeanDefinitionException
:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [ServiceB] found for dependency [ServiceB]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
I'm using Spring Boot version 1.4.0
If you try to use @Autowired on an interface, the Spring framework would throw an exception as it won't be able to decide which implementation class to use.
@Bean is just for the metadata definition to create the bean(equivalent to tag). @Autowired is to inject the dependancy into a bean(equivalent to ref XML tag/attribute).
Using Java Configuration In this approach, we'll use a Java-based configuration class to configure multiple beans of the same class. Here, @Bean instantiates two beans with ids the same as the method names and registers them within the BeanFactory (Spring container) interface.
NoUniqueBeanDefinitionException. Another similar cause for the bean creation exception is Spring trying to inject a bean by type, namely by its interface, and finding two or more beans implementing that interface in the context.
Yes it is possible, but
it is important, to create the service bean of type ServiceImpl
and not as one of the service interfaces :
@Bean
ServiceImpl service() {
return new Serviceimpl();
}
Spring uses reflection on the declared bean type to find out which interfaces it implements and not on bean.getClass()
.
Even if this answer was voted dowen, you can be asured : it works . If it does not work for you @scarba05, your problem must be somewhere else...
You could use the @Qualifier
annotation. It can be applied alongside @Autowired
or @Inject
at the point of injection to specify which bean you want to be injected:
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
Source: Spring in Action 4th edition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With