You can exclude a bean from autowiring in Spring framework per-bean basis. If you are using
Spring XML configuration
then you can exclude a bean from autowiring by setting the autowire-candidate
attribute of the <bean/> element
to false. That way container makes that specific bean definition unavailable to the autowiring infrastructure.
Excluding bean using autowire-candidate example
Here we have a class PayServiceImpl
which has a field payment of type IPayment
which we have to autowire.
Also there are two classes CashPayment
and CardPayment
which implements IPayment interface.
IpayService interface
public interface IPayService{ void performPayment(); }
PayServiceImpl class
import org.springframework.beans.factory.annotation.Autowired; public class PayServiceImpl implements IPayService{ @Autowired private IPayment payment; public void setPayment(IPayment payment) { this.payment = payment; } public void performPayment() { System.out.println("performPayment Method called"); payment.executePayment(); } }
Here note the @Autowired annotation on payment field.
Interface Ipayment
public interface IPayment{ void executePayment(); }
CashPayment class
public class CashPayment implements IPayment{ public void executePayment() { System.out.println("Perform Cash Payment "); } }
CardPayment class
public class CardPayment implements IPayment{ public void executePayment() { System.out.println("Perform Card Payment "); } }
XML Configuration
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <bean id="cash" class="org.netjs.exp.Spring_Example.CashPayment" /> <bean id="card" class="org.netjs.exp.Spring_Example.CardPayment" /> <bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PayServiceImpl"> </bean> </beans>
Here we have defined two beans of type Ipayment, CashPayment
and CardPayment
. This will result in BeanCreationException
as container won’t be able to decide which on of the two inject in PayServiceImpl class.
You can check that by running the code using the following Java class.
import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main( String[] args ){ AbstractApplicationContext context = new ClassPathXmlApplicationContext ("appcontext.xml"); IPayService payBean = (IPayService)context.getBean("payServiceBean"); payBean.performPayment(); context.registerShutdownHook(); } }
Output
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'payServiceBean': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.netjs.exp.Spring_Example.IPayment org.netjs.exp.Spring_Example.PayServiceImpl.payment; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.netjs.exp.Spring_Example.IPayment] is defined: expected single matching bean but found 2: cash,card Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.netjs.exp.Spring_Example.IPayment] is defined: expected single matching bean but found 2: cash,card
If you set autowire-candidate attribute as false for one of the bean then the problem will be resolved.
<bean id="cash" class="org.netjs.exp.Spring_Example.CashPayment" autowire-candidate="false" />
With this change if you run the code, card bean will be injected.
Output
performPayment Method called Perform Card Payment
Resolving conflict with annotations
If you want to use annotations to resolve conflict in this type of situation when you have more than one bean defined of the same type. Then you have two options.
- @Qualifier annotation.
- @Inject and @Named annotation
Using @Qualifier annotation example
In the example used above where you have two beans CardPayment and CashPayment of the same type, in order to avoid ambiguity
you can use @Qualifier
annotation to qualify the bean.
Suppose you want to inject cashPaymentBean then you can qualify it by passing bean name with the qualifier annotation in the PayServiceImpl class.
PayServiceImpl.java
public class PayServiceImpl implements IPayService{ @Autowired @Qualifier("cash") private IPayment payment; public void setPayment(IPayment payment) { this.payment = payment; } public void performPayment() { System.out.println("performPayment Method called"); payment.executePayment(); } }
Now even if you don’t set autowire-candidate as false for any of the bean that’s ok as @Qualifier annotation will resolve the conflict.
<bean id="cash" class="org.netjs.exp.Spring_Example.CashPayment" /> <bean id="card" class="org.netjs.exp.Spring_Example.CardPayment" />
Using @Inject and @Named annotations
If you want to make sure that CashPayment bean is the one which is injected then using @Inject
and @Named
annotations the PayServiceImpl class will look like-
import javax.inject.Inject; import javax.inject.Named; public class PayServiceImpl implements IPayService{ @Inject @Named("cash") private IPayment payment; public void setPayment(IPayment payment) { this.payment = payment; } public void performPayment() { System.out.println("performPayment Method called"); payment.executePayment(); } }
Note that you will need to import javax.inject jar in order to use these annotations. In Maven you can do it by adding the following dependency.
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
That's all for this topic Excluding Bean From Autowiring in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Spring Tutorial Page
Related Topics
You may also like-
No comments:
Post a Comment