Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autowire Spring bean implementing two interfaces

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

like image 222
scarba05 Avatar asked Oct 07 '16 14:10

scarba05


People also ask

Can we use @autowired for interface?

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.

What is difference between @bean and @autowire?

@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).

Can we use two beans in one interface?

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.

What type of Spring exception is raised when two or more bean implementing that interface in the context?

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.


2 Answers

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...

like image 53
Stefan Isele - prefabware.com Avatar answered Sep 22 '22 12:09

Stefan Isele - prefabware.com


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.

like image 32
sirandy Avatar answered Sep 19 '22 12:09

sirandy