logo

Autowiring In Spring Bean


Show

Autowiring in the Spring framework is a feature that enables you to inject the object dependency in an implicit manner. It uses setter or constructor injection internally. By using Autowiring, you can automatically detect the relationships between various beans in Spring. Ultimately, autowiring will enable Spring to resolve collaborators or other beans for your beans by inspecting the contents of the BeanFactory. You need not to write and elements in Autowiring, hence it simplifies XML configuration for a big Spring-based application. It is an easy way of doing dependency injection in Spring.

The main thing about Autowiring is that it can't be used to inject primitive and string values. It only uses the reference to do this.

Modes of Autowiring:

There are five types of modes of Autowiring that are supported by the Spring to allow the Spring container to inject the dependency. You can use the autowire attribute of the bean element to specify autowire mode to define the bean.

no

It is the default autowiring mode which means there is no autowiring. In this mode, you are advised to use explicit bean reference for wiring. There is nothing special about this type of Autowiring as having already seen this in Dependency Injection tutorials.

byName

This mode is also called Autowiring by property name. This mode of Autowiring injects the object dependency based on the name of the bean. To use this mode, you must confirm that the property name and bean name are the same that are needed to be autowired. Here, the setter method is called internally. In this mode, the Spring container looks for the properties of those beans that have an autowire attribute as byName in the XML configuration file. It then attempts to match and wire its properties with the beans with the same names in the configuration file.

byType

It is also called Autowiring by property datatype. This mode injects the object dependency according to type, so that property name and bean name can be dissimilar. This mode internally calls the setter method. This mode allows the property to be autowired in case of only one bean in the container, otherwise, a fatal exception will be thrown.

constructor

This mode injects the dependency by calling the constructor of the class. Here, a constructor is called that has a large number of parameters. In this method, spring looks for the type of constructor argument in the configuration file. This mode is similar to the byType mode but it applies to constructor arguments. If there exists more than one bean of the constructor argument type in the container, a fatal error will be raised.

autodetect

In this mode, At first, Spring tries to autowire by the constructor, if it doesn’t work, then it will try by using byType mode. This method automatically performs two autowiring based on the matching constructor. If it is found, then this mode will use autowire by the constructor, otherwise, it will use the autowire by type.

Examples of Autowiring

Now we will use the simple code to perform autowiring in Spring. Here you are required to use the autowire attribute of the bean element to apply the autowire modes.

<bean id="a" class="org.sssit.A" autowire="byName"></bean>

Now we will see the full example of Autowiring in spring to create the above example. we have created four files that are listed below:

  • B.java
  • A.java
  • applicationContext.xml
  • Test.java

Now we will study these classes briefly:

B.java

This class only includes a constructor and a method.

package org.sssit;  
public class B {  
B(){System.out.println("b is created");}  
void print(){System.out.println("hello b");}  
}

A.java

This class has a constructor and a method as well as a reference of B class.

package org.sssit;  
public class A {  
B b;  
A(){System.out.println("a is created");}  
public B getB() {  
    return b;  
}  

public void setB(B b) {  
    this.b = b;  
}  

void print(){System.out.println("hello a");}  
void display(){  
    print();  
    b.print();  
}  
}  

ApplicationContext.xml

It is also known as the Spring bean configuration file, which is the backbone of any Spring application.

  
<beans  
    xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:p="http://www.springframework.org/schema/p"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  
<bean id="b" class="org.sssit.B"></bean>  
<bean id="a" class="org.sssit.A" autowire="byName"></bean>  
</beans>

Test.java

This class gets the bean from the applicationContext.xml file and calls the display method to display the output.

package org.sssit;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class Test {  
public static void main(String[] args) {  
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");  
    A a=context.getBean("a",A.class);  
    a.display();  
}  
}  

The output of the above example will look like below:

b is created
a is created
hello a
hello b

Now we will study the use of Autowiring modes with coded examples:

Autowiring ‘no’:

This is a default autowiring mode. It means no autowiring. In this case, the spring container doesn't inject the dependency by autowiring.

<bean id="b" class="org.sssit.B"></bean>  
<bean id="a" class="org.sssit.A" autowire="no"></bean> 

Autowiring ‘byName’:

In the case of byName autowiring mode, bean id and reference name must be the same inside the spring configuration file.

It internally uses setter injection.

<bean id="b" class="org.sssit.B"></bean>  
<bean id="a" class="org.sssit.A" autowire="byName"></bean> 

In case if you change the name of the bean, dependency injection will not be performed by this mode of Autowiring. In the following code, we are changing the name of the bean from b to b1.

<bean id="b1" class="org.sssit.B"></bean>  
<bean id="a" class="org.sssit.A" autowire="byName"></bean>  

Autowiring ‘byType’:

In the case of byType autowiring mode, there is a possibility that the bean id and the reference name may be different. But this mode will work on the condition that says that there is only one bean of a type in the spring configuration file. This mode internally uses setter injection.

<bean id="b1" class="org.sssit.B"></bean>  
<bean id="a" class="org.sssit.A" autowire="byType"></bean> 

Here in this example, it is ok because we have created an instance of B type. So there is no such issue that you have a different bean name than a reference name. But in case you have several beans of one type, it will not work and throw an exception.

Let's see the code below which mentions many beans of type B.

<bean id="b1" class="org.sssit.B"></bean>  
<bean id="b2" class="org.sssit.B"></bean>  
<bean id="a" class="org.sssit.A" autowire="byName"></bean>

In the above scenario, this autowiring mode will throw an exception.

Autowiring ‘constructor’

In constructor mode, the spring container injects the dependency by the constructor of the highest parameter. In the condition of having three constructors in a class, zero-arg, one-arg, and two-arg then injection will be performed by calling the two-arg constructor. See the code below:

<bean id="b" class="org.sssit.B"></bean>  
<bean id="a" class="org.sssit.A" autowire="constructor"></bean>

Autowiring ‘autodetect’

The autodetect mode of autowiring uses two modes that are either constructor or byType. It will use these two modes based on the search for a valid constructor with arguments. If it finds the valid constructor then constructor mode will be used otherwise byType mode will be chosen.

In this example, the autodetect autowiring will use the constructor mode as class b has a valid constructor type.

@Autowired Annotation

In the Spring framework, you can auto-wire beans on the setter method, constructor, or field method by using the @Autowired Annotation. It can also autowire the property in a particular bean. Before using the autowired annotation we first need to enable the annotation using a configuration that is mentioned below in the configuration file. In the Java-based configuration, you can perform the annotation-driven injection by the code as mentioned below:

@Configuration
@ComponentScan("guru.springframework.autowiringdemo")
public class AppConfig {}

You can also have the option of using the XML-based configuration in Spring that is:

<context:annotation-config />

Now we have enabled annotation injection. Now, it will be ready to use on the modes like properties, setters, and constructors. We will study them in the below section.

@Autowired on Properties

When the annotation is directly used on properties as mentioned in the below example, Spring searches for and injects Department class when Employee class is created. As a result, we don’t need to use the getters and setters.

import org.springframework.stereotype.Component;
@Component
public class Department {
private String deptName;
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
}
import org.springframework.beans.factory.annotation.Autowired;
public class Employee {
    private int eid;
    private String ename;
    @Autowired
    private Department department;
    public int getEid() {
        return eid;
    }
    public void setEid(int eid) {
        this.eid = eid;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    public void showEployeeDetails(){
        System.out.println("Employee Id : " + eid);
        System.out.println("Employee Name : " + ename);
        department.setDeptName("Information Technology");
        System.out.println("Department : " + department.getDeptName());
    }
}

@Autowired on Setters

When the annotation is used on the setter method, the setter method will be invoked with the instance of the Department when an Employee class is created.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Employee {
    private int eid;
    private String ename;
    private Department department;
    public int getEid() {
        return eid;
    }
    public void setEid(int eid) {
        this.eid = eid;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    public Department getDepartment() {
        return department;
    }
    @Autowired
    public void setDepartment(Department department) {
        this.department = department;
    }
    public void showEployeeDetails(){
        System.out.println("Employee Id : " + eid);
        System.out.println("Employee Name : " + ename);
        department.setDeptName("Information Technology");
        System.out.println("Department : " + department.getDeptName());
    }
}

@Autowired on Constructors

Here, an annotation is used on a constructor. It injects the instance of the department class which is used as an argument to the constructor after the creation of the Employee class.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Employee {
    private int eid;
    private String ename;
    private Department department;
    @Autowired
    public EmployeeBean(DepartmentBean deptBean) {
        System.out.println("*** Autowiring by using @Autowire annotation on constructor ***");
        this.deptBean = deptBean;
    }
    public int getEid() {
        return eid;
    }
    public void setEid(int eid) {
        this.eid = eid;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    public Department getDepartment() {
        return department;
    }
    public void setDepartment(Department department) {
        this.department = department;
    }
    public void showEployeeDetails(){
        System.out.println("Employee Id: " + eid);
        System.out.println("Employee Name: " + ename);
        department.setDeptName("Information Technology");
        System.out.println("Department : " + department.getDeptName());
    }
}

Writing a Test Class

Now, we can experiment with the effect of the @Autowired on the property. To run the program, just follow the code below:

@SpringBootApplication
public class AutowiringdemoApplication {
  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(AutowiringdemoApplication.class, args);
    Employee emp = context.getBean(Employee.class);
    emp.setEid(104);
    emp.setEname("Spring Framework Guru");
    emp.showEployeeDetails();
  }
}

After the successful running of the above program, we get the following output result:

Employee Id: 104 
Employee Name: Spring Framework Guru 
Department: Information Technology 
Process finished with exit code 0

Limitations with Autowiring

Autowiring can be a great way of finding the dependencies between the objects if it is used consistently. Otherwise, the developers may get confused about using it to wire on either only one or two bean definitions. Despite being one of the best methods to reduce the need to specify properties or constructor arguments, Autowiring can have some drawbacks as well.

Below are some of the limitations of the autowiring that can persist:

  • A chance of getting the dependency that exists using constructor-arg and property settings which will always override autowiring.
  • In Autowiring, you are not able to autowire some simple properties like primitives, Strings, and Classes.
  • Autowiring is less demanding than its Explicit counterpart, so it is advised to use Explicit wiring whenever possible.

Resolution of Autowire Conflict

By default, Spring resolves @Autowired entries by using byType mode. If there is more than one bean of the same type present in the container, the Spring framework will throw a NoUniqueBeanDefinitionException exception, which indicates that more than one bean is available for autowiring.