Though autowiring of the beans can be done using
XML configuration for autowiring but Spring goes one step
further and provides autowiring using annotations which leads to shorter and more concise configuration.
Broadly Spring provides two ways to annotate beans for autowiring-
- Using @Autowired annotation- It is a spring specific annotation.
- Using @Inject annotation- It is provided by JSR-330 (Dependency Injection for Java) annotations
contained in the javax.inject package. Spring supports this annotation.
In this post we'll see Spring autowiring examples using both @Autowired and @Inject annotations.
Configuration required for autowiring using annotation
To enable autowiring using annotation in Spring, you have to register 'AutowiredAnnotationBeanPostProcessor' class.
- You can directly provide this class in xml config-
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
- You can include the <context:annotation-config/> tag in an XML-based Spring configuration
(notice the inclusion of the context namespace in XML). This is the preferred way.
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
By using <context:annotation-config/> tag following post-processors are implicitly registered AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor and RequiredAnnotationBeanPostProcessor.
- You can include the <context:component-scan/> tag.
Refer
Using component-scan in Spring to Automatically Discover Bean to see why <context:component-scan/> should be used instead
of <context:annotation-config/>
Autowiring in Spring using @Autowired annotation
Note that @Autowired annotation can be applied on-
- setter method
- constructor
- field
Here we'll see example for all of these options.
Spring @Autowired annotation on setter
When @Autowired annotation is used on a setter, it is equivalent to autowiring="byType" in autowiring using configuration file.
Here we have a class PayServiceImpl which has a field payment of type IPayment which we have to autowire.
Also class CashPayment which implements IPayment interface.
interface IPayService
public interface IPayService {
void performPayment();
}
PayServiceImpl class
import org.springframework.beans.factory.annotation.Autowired;
public class PayServiceImpl implements IPayService {
private IPayment payment;
public void performPayment() {
// calling method on Ipayment implementing class
payment.executePayment();
}
public IPayment getPayment() {
return payment;
}
@Autowired
public void setPayment(IPayment payment) {
this.payment = payment;
}
}
Here note the @Autowired annotation on setPayment() method.
Interface IPayment
public interface IPayment {
void executePayment();
}
CashPayment class
public class CashPayment implements IPayment{
public void executePayment() {
System.out.println("Perform Cash Payment - ");
}
}
XML configuration file
<?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:aop="http://www.springframework.org/schema/aop"
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="cashPaymentBean" class="org.netjs.prog.CashPayment" />
<!-- Defining PayServiceImpl bean and injecting payment bean -->
<bean id="paymentBean" class="org.netjs.prog.PayServiceImpl">
<!-- <property name="payment" ref="cashPaymentBean" /> -->
</bean>
</beans>
Here note the inclusion of <context:annotation-config/> tag which is required for autowired annotation.
Also note that ref for cashPaymentBean is no longer required as a property in paymentBean
(it is commented in the config). It will be injected automatically now because of the @Autowired annotation.
You can use the following code to run this program -
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main( String[] args ){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("appcontext.xml");
// Getting PayServiceImpl
IPayService bean = (IPayService) context.getBean("paymentBean");
bean.performPayment();
context.close();
}
}
Output
Perform Cash Payment-
@Autowired annotation on field
When @Autowired annotation is used on a property, it is equivalent to autowiring="byType" when autowiring is done using configuration file.
In this case PayServiceImpl will change to have @Autowired annotation on the field. When using @Autowired with field you don't even need the setter method for that field.
PayServiceImpl class
public class PayServiceImpl implements IPayService {
@Autowired
private IPayment payment;
public void performPayment() {
// calling method on Ipayment implementing class
payment.executePayment();
}
public IPayment getPayment() {
return payment;
}
/*public void setPayment(IPayment payment) {
this.payment = payment;
}*/
}
Rest of the things remain the same as used in the example for @Autowired on setter.
@Autowired annotation on constructor
When @Autowired annotation is used on a bean's constructor, it is equivalent to autowiring="constructor" when autowiring is done using configuration file.
In this case PayServiceImpl will change to have @Autowired annotation on the constructor of the class.
When using @Autowired on constructor you don't even need the setter method for that field.
import org.springframework.beans.factory.annotation.Autowired;
public class PayServiceImpl implements IPayService {
private IPayment payment;
// Constructor
@Autowired
PayServiceImpl(IPayment payment){
this.payment = payment;
}
public void performPayment() {
// calling method on Ipayment implementing class
payment.executePayment();
}
public IPayment getPayment() {
return payment;
}
/*public void setPayment(IPayment payment) {
this.payment = payment;
}*/
}
Rest of the things remain the same as used in the example for @Autowired on setter.
@Autowired annotation on arbitrary methods
You can also apply the annotation to methods with arbitrary names and/or multiple arguments, Example as taken from
Spring reference doc
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
@Autowired annotation with required=false
The default behavior for the annotation is to treat annotated methods, constructors, and fields as indicating
required dependencies. Thus the autowiring fails whenever zero candidate beans are available. You can
make the autowiring optional to avoid such errors, this can be done by using required="false" with the
@Autowired annotation.
@Autowired(required=false)
private IPayment payment;
Conflict resolution using Spring @Qualifier annotation
What if there are more than one bean in the configuration file whose type is compatible with the autowired
property. In that case Spring won't be able to decide which bean to use, it will throw an exception instead.
In the above application we had used only one implementation of IPayment, CashPayment so there was no problem
in automatically wiring it. Now suppose we have one more implementation of the IPayment interface,
Credit Payment. In that case with the current setup you'll get NoUniqueBeanDefinitionException because
Spring won't know which Payment class to wire.
CreditPayment class
public class CreditPayment implements IPayment {
public void executePayment() {
System.out.println("Performing credit payment ");
}
}
Adding CreditPayment definition in config
<bean id="creditPaymentBean" class="org.netjs.prog.CreditPayment" />
Now if you run the code you will get NoUniqueBeanDefinitionException-
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paymentBean':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.netjs.prog.IPayment org.netjs.prog.PayServiceImpl.payment;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.netjs.prog.IPayment] is defined: expected single matching bean but found 2:
cashPaymentBean,creditPaymentBean
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
In this kind of scenario, 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.
@Qualifier example to avoid NoUniqueBeanDefinitionException error
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class PayServiceImpl implements IPayService {
@Autowired
@Qualifier("cashPaymentBean")
private IPayment payment;
public void performPayment() {
// calling method on Ipayment implementing class
payment.executePayment();
}
public IPayment getPayment() {
return payment;
}
/*public void setPayment(IPayment payment) {
this.payment = payment;
}*/
}
Using JSR-330 @Inject annotation
Instead of @Autowired, @javax.inject.Inject annotation can be used for autowiring in Spring. @Inject annotation
is part of the standard JSR-330: Dependency injection for Java. So, if you don't want Spring specific annotations and
want to go with standard annotation then use @Inject.
As with @Autowired, it is possible to use @Inject at the class-level, field-level, method-level and
constructor-argument level.
Note one thing though. @Inject has no 'required' attribute as provided with @Autowired, so @Inject annotated
dependencies can't be optional, an exception will be thrown if they are not fulfilled.
@Named annotation
If you would like to use a qualified name for the dependency that should be injected, instead of @Qualifier
you can use @Named annotation which is again part of the standard JSR-330: Dependency injection for Java.
Spring autowiring example with @Inject and @Named annotations
Let's take the same case where we have two payment classes CashPayment and CreditPayment. 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("cashPaymentBean")
private IPayment payment;
public void performPayment() {
// calling method on Ipayment implementing class
payment.executePayment();
}
public IPayment getPayment() {
return payment;
}
@Inject
public void setPayment(@Named("cashPaymentBean")IPayment payment) {
this.payment = payment;
}
}
Note here that @Inject annotation is used with the setter.
Configuration file for the example
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
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="cashPaymentBean" class="org.netjs.prog.CashPayment" />
<bean id="creditPaymentBean" class="org.netjs.prog.CreditPayment" />
<!-- Defining PayServiceImpl bean and injecting payment bean -->
<bean id="paymentBean" class="org.netjs.prog.PayServiceImpl">
</bean>
</beans>
Are annotations better than XML for configuring Spring?
According to the Spring reference doc-
The introduction of annotation-based configurations raised the question of whether this approach
is 'better' than XML. The short answer is it depends. The long answer is that each approach has
its pros and cons, and usually it is up to the developer to decide which strategy suits them better.
Due to the way they are defined, annotations provide a lot of context in their declaration, leading
to shorter and more concise configuration. However, XML excels at wiring up components without
touching their source code or recompiling them. Some developers prefer having the wiring close
to the source while others argue that annotated classes are no longer POJOs and, furthermore,
that the configuration becomes decentralized and harder to control.
That's all for this topic Autowiring in Spring Using @Autowired and @Inject Annotations. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
-
Autowiring in Spring Using XML Configuration
-
Dependency Injection in Spring Framework
-
How to Read Properties File in Spring Framework
-
Difference Between component-scan And annotation-config in Spring
-
@Resource Annotation in Spring Autowiring
You may also like-
-
Bean Definition Inheritance in Spring
-
Spring p-namespace For Shorter XML Configuration
-
Spring NamedParameterJdbcTemplate Insert, Update And Delete Example
-
Difference Between throw And throws in Java
-
How to Sort an ArrayList in Descending Order in Java
-
LinkedHashMap in Java With Examples
-
How to Create PDF From XML Using Apache FOP
-
How to Find Last Modified Date of a File in Java