Spring Autowiring by using the “autowire” attribute in the bean configuration file we can wire all the properties of the bean class. Using Spring Autowiring through XML you cannot wire a particular property. In those cases we can use the Spring @Autowired annotation which allows auto-wiring of setter method, a constructor, a field, or even an arbitrary method.
Folder Structure:
- Create a new Java Project “SpringCoreTutorial” and create a package for our src files “com.javainterviewpoint“
- Add the required libraries to the build path. Java Build Path ->Libraries ->Add External JARs and add the below jars.
commons-logging-1.2.jar
spring-beans-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-context-4.2.4.RELEASE.jar
spring-expression-4.2.4.RELEASE.jar - Create the Java classes Employee.java, PermanentEmployee.java and EmployeeLogic.java under com.javainterviewpoint folder.
- Place our configuration file SpringConfig.xml in the src directory
SpringConfig.xml
<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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config></context:annotation-config> <bean id="emp" class="com.javainterviewpoint.Employee"></bean> <bean id="permemp" class="com.javainterviewpoint.PermanentEmployee"></bean> </beans>
- We have declared two beans one for our Employee class and and other for our PermanentEmployee class, we have not injected any reference to the property “pe” of our Employee class.
Spring AutoWiring @Autowired Annotation over Setter Method
@Autowired annotation can be applied to any particular property, in this Spring autowiring example lets autowire the setter method of the “pe” property with @Autowired annotation. Spring container will try to wire a bean which is compatible to type “PermanentEmployee”
Employee.java
Our Employee class has a property “pe” and we have added the @Autowire annotation over its setter method.
package com.javainterviewpoint; import org.springframework.beans.factory.annotation.Autowired; public class Employee { private PermanentEmployee pe; public Employee() { super(); } public Employee(PermanentEmployee pe) { super(); this.pe = pe; } public PermanentEmployee getPe() { return pe; } @Autowired public void setPe(PermanentEmployee pe) { this.pe = pe; } }
PermanentEmployee.java
package com.javainterviewpoint; public class PermanentEmployee { private Employee employee; private int Salary; public PermanentEmployee() { super(); } public PermanentEmployee(Employee employee, int salary) { super(); this.employee = employee; Salary = salary; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public int getSalary() { return Salary; } public void setSalary(int salary) { Salary = salary; } }
EmployeeLogic.java
package com.javainterviewpoint; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class EmployeeLogic { public static void main(String args[]) { //Read the Configuration file using ApplicationContext ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringConfig.xml"); //Get the Employee class instance Employee employee = (Employee)applicationContext.getBean("emp"); //Print the PermanentEmployee details System.out.println("**** Employee Details ****"); //Setting the salary employee.getPe().setSalary(100); //Retrieving the Permanent Employee salary System.out.println(employee.getPe().getSalary()); } }
- In our EmployeeLogic class we have read the Configuration file(SpringConfig.xml) and get all the bean definition through ApplicationContext
- Get the Employee Class instance by calling the getBean() method over the context created.
- Through the getPe() we will get the “PermanentEmployee” and using it we will be setting and retrieving the value of the salary property.
Output :
Upon running the EmployeeLogic class we will be getting the below output.
Spring @Autowired Annotation over Constructor
In addition to Setter method @Autowired annotation can be applied to the Constructor as well, spring will try to wire the bean compatible type of each Constructor argument. Here PermanentEmployee is the constructor argument, so the bean compatible to type PermanentEmployee will be injected.
package com.javainterviewpoint; import org.springframework.beans.factory.annotation.Autowired; public class Employee { private PermanentEmployee pe; public Employee() { super(); } @Autowired public Employee(PermanentEmployee pe) { super(); this.pe = pe; } public PermanentEmployee getPe() { return pe; } public void setPe(PermanentEmployee pe) { this.pe = pe; } }
Spring @Autowired Annotation over array / collections
@Autowired annotation can also be applied to a property of array type or java collection. Lets say, if you annotate the property PermanentEmployee[] or List<PermanentEmployee> with @Autowired, Spring will auto-wire all the beans whose type is compatible with PermanentEmployee.
package com.javainterviewpoint; import org.springframework.beans.factory.annotation.Autowired; public class Employee { @Autowired private PermanentEmployee[] pe; public Employee() { super(); } public Employee(PermanentEmployee pe) { super(); this.pe = pe; } public PermanentEmployee getPe() { return pe; } public void setPe(PermanentEmployee pe) { this.pe = pe; } }
required attribute @Autowired annotation
By default, all the properties with @Autowired are required. Whenever Spring can’t find a matching bean to wire, it will be throwing BeanCreationException.
But there will time when you want some property to be optional, then we can set the “required” attribute of @Autowired to false so if Spring cannot find the matching bean it will not be throwing exception.
package com.javainterviewpoint; import org.springframework.beans.factory.annotation.Autowired; public class Employee { private PermanentEmployee pe; public Employee() { super(); } public Employee(PermanentEmployee pe) { super(); this.pe = pe; } public PermanentEmployee getPe() { return pe; } @Autowired(required = false) public void setPe(PermanentEmployee pe) { this.pe = pe; } }
Use of @Qualifier annotation Spring – AutoWiring byName
Autowiring byType will not work when there is more than one bean of same type declared. We will be getting BeanCreationException / NoUniqueBeanDefinitionException Exception
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.javainterviewpoint.Employee.setPe(com.javainterviewpoint.PermanentEmployee); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.javainterviewpoint.PermanentEmployee] is defined: expected single matching bean but found 2: permemp1,permemp2 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:661) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ... 13 more Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.javainterviewpoint.PermanentEmployee] is defined: expected single matching bean but found 2: permemp1,permemp2 at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:618) ... 15 more
Spring AutoWiring has the solution for it, we can use the @Qualifier annotation by providing the name of the required bean.
Our configuration file will be like below
<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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config></context:annotation-config> <bean id="emp" class="com.javainterviewpoint.Employee"></bean> <bean id="permemp" class="com.javainterviewpoint.PermanentEmployee"></bean> <bean id="permemp2" class="com.javainterviewpoint.PermanentEmployee"></bean> </beans>
Now we can use the @Qualifier annotation to select the required property type. Now our Employee class will be re-written like below
package com.javainterviewpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Employee
{
private PermanentEmployee pe;
public Employee()
{
super();
}
public Employee(PermanentEmployee pe)
{
super();
this.pe = pe;
}
public PermanentEmployee getPe()
{
return pe;
}
@Autowired
@Qualifier("permemp2")
public void setPe(PermanentEmployee pe)
{
this.pe = pe;
}
}
Spring @Resource annotation
When ever you want to implement Spring autowiring byName using annotation, you can annotate a setter method, a constructor, or a field with @Resource annotation which is based on JSR-250. Spring will attempt to find if any bean is declared in the configuration file with property name. You can also specify the bean name explicitly using the name attribute.
<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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config></context:annotation-config> <bean id="emp" class="com.javainterviewpoint.Employee"></bean> <bean id="pe" class="com.javainterviewpoint.PermanentEmployee"></bean> <bean id="permemp2" class="com.javainterviewpoint.PermanentEmployee"></bean> </beans>
Now we can use the @Qualifier annotation to select the required property type. Now our Employee class will be re-written like below
package com.javainterviewpoint; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; public class Employee { private PermanentEmployee pe; public Employee() { super(); } public Employee(PermanentEmployee pe) { super(); this.pe = pe; } public PermanentEmployee getPe() { return pe; } @Resource(name="pe") public void setPe(PermanentEmployee pe) { this.pe = pe; } }
@Inject annotation Spring
Spring 3.0 supports JSR 330 standard : Dependency Injection for Java. In Spring 3 application, we can use @Inject instead of Spring’s @Autowired to inject a bean. The JSR 330 Standard @Inject annotation works exactly the same like Spring’s @Autowired annotation. In order to use @Inject annotation we need to add “javax.inject-1.jar” into our project.
package com.javainterviewpoint; import javax.inject.Inject; public class Employee { private PermanentEmployee pe; public Employee() { super(); } public Employee(PermanentEmployee pe) { super(); this.pe = pe; } public PermanentEmployee getPe() { return pe; } @Inject public void setPe(PermanentEmployee pe) { this.pe = pe; } }
Pitfalls of @Inject over @Autowired
- @Inject annotation doesn’t have the required attribute unlike @Autowired annotation, so that we can make a filed mandatory or optional.
- JSR 330 @Inject annotation is Singleton by default. But in Spring we can use other scopes as well using the @Scopes annotation.
Difference Between @Resource, @Autowired and @Inject in Spring Injection
Leave a Reply