Autowiring is a feature in Spring that allows the Spring IoC container to automatically resolve and inject bean dependencies, rather than explicitly specifying them in the configuration. It simplifies Dependency Injection by reducing boilerplate code and automatically linking related beans based on certain matching criteria.

Types of Autowiring

  • no (Default)
    • Autowiring is disabled. You must explicitly define all dependencies in the XML configuration or using annotations.
  • byName
    • Spring matches the property name of the dependent bean with the ID of the candidate bean.
  • byType
    • Spring matches the type of the property with the type of the candidate bean.
  • constructor
    • Spring matches constructor parameters with candidate beans based on type.

By name

Spring resolves the dependency by matching the bean ID (computer) with the property name (computer).

<bean id="person" class="com.example.Person" autowire="byName" />
<bean id="computer" class="com.example.Computer" />
public class Person {
	// Property name matches the bean ID "computer"
    private Computer computer; 
    
    public void setComputer(Computer computer) {
        this.computer = computer;
    }
}

In the below example: Spring:

  1. Inspects the person bean’s properties in the XML configuration. The person bean has autowire="byName", so Spring will attempt to inject dependencies based on the names of the Person class’s properties (computer).
  2. The container also has a bean with ID "computer" and type com.example.Laptop.
  3. For each property, Spring looks for a bean in the container whose ID matches the property name (computer).
  4. If a match is found, Spring invokes the corresponding setter method to inject the dependency.
<bean id="person" class="com.example.Person" autowire="byName"/>  
<bean id="computer" class="com.example.Laptop" />
public interface Computer {  
    void compile();  
}
 
public class Desktop implements Computer {  
    @Override  
    public void compile() {  
        System.out.println("The desktop is compiling...");  
    }  
}
 
public class Laptop implements Computer {  
    @Override  
    public void compile() {  
        System.out.println("The laptop is compiling...");  
    }  
}
 
public class Person {  
    // Property name matches the bean ID "computer"
    Computer computer;  
    
    public void code() {  
        computer.compile();  
    }  
    
    public void setComputer(Computer computer) {  
        System.out.println("Setter called");  
        this.computer = computer;  
    }
}
public class App {
	    public static void main(String[] args) {  
	        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
	        Person p1 = (Person) context.getBean("person");  
	        p1.code();  
	    }  
	}
}
Setter called
The laptop is compiling...
Coding..

Spring calls the setComputer(Computer computer) setter method in the Person class and passes the "computer" bean (Laptop object) as the argument.

If we want to swap the Laptop with Desktop since they both implement the Computer interface. We only need to change the XML configuration and make the bean id computer of type Desktop.

<bean id="person" class="com.example.Person" autowire="byName" />
<bean id="computer" class="com.example.Desktop" />

When we run the program the output shows as below.

Setter called
The desktop is compiling...
Coding...

By type

Spring resolves the dependency by matching the type of the property (Computer) with the type of the available bean.

<bean id="person" class="com.example.Person" autowire="byType" />
 
<!-- type of Computer -->
<bean id="computerBean" class="com.example.Computer" /> 
public class Person {
	// Type matches the bean type "Computer"
    private Computer computer; 
    
    public void setComputer(Computer computer) {
        this.computer = computer;
    }
}

In the below example: Spring:

  1. Inspects the person bean’s properties in the XML configuration. The person bean has autowire="byType", so Spring will attempt to inject dependencies based on the type of the Person class’s properties (Computer).
  2. The container has a bean with ID "lap" which is of the desired type Computer (the laptop class implements the Computer interface).
  3. For each property, Spring looks for a bean in the container whose type matches the property type (Computer).
  4. If a match is found, Spring invokes the corresponding setter method to inject the dependency.
<bean id="person" class="com.example.Person" autowire="byType"/>  
<bean id="lap" class="com.example.Laptop" />
public interface Computer {  
    void compile();  
}
 
public class Desktop implements Computer {  
    @Override  
    public void compile() {  
        System.out.println("The desktop is compiling...");  
    }  
}
 
public class Laptop implements Computer {  
    @Override  
    public void compile() {  
        System.out.println("The laptop is compiling...");  
    }  
}
 
public class Person {  
	// Type matches the bean type "Computer"
    Computer computer;  
    
    public void code() {  
        computer.compile();  
    }  
    
    public void setComputer(Computer computer) {  
        System.out.println("Setter called");  
        this.computer = computer;  
    }
}
public class App {
	    public static void main(String[] args) {  
	        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
	        Person p1 = (Person) context.getBean("person");  
	        p1.code();  
	    }  
	}
}
Setter called
The laptop is compiling...
Coding..

Even though the bean ID (lap) does not match the property name (computer), since the autowiring is set to by type, Spring looks for the bean of the type Computer (property type). The bean ID lap is of the type Computer, it is wired with Person.

However, if you have two beans of the same Computer type (Laptop and Desktop both implement Computer), Spring will pose an error.

<bean id="person" class="com.example.Person" autowire="byType"/>  
<bean id="lap" class="com.example.Laptop" />  
<bean id="desk" class="com.example.Desktop" />
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person' defined in class path resource [applicationContext.xml]: Unsatisfied dependency expressed through bean property 'computer': No qualifying bean of type 'com.tim.Computer' available: expected single matching bean but found 2: lap,desk

In byType autowiring mode, Spring attempts to resolve a property by looking for a single bean of the same type as the property in the Spring context. If there are multiple beans of the same type (Laptop and Desktop), Spring cannot decide which one to inject and throws a NoUniqueBeanDefinitionException.

Primary bean

Using a primary attribute on bean can solve the confusion of Spring about which bean of the same type to chose. Here we add the primary attribute to lap and set it to true. This tells Spring to select lap as the bean of choice when there are more than one bean of the same type.

<bean id="person" class="com.example.Person" autowire="byType"/>  
<bean id="lap" class="com.example.Laptop" primary="true" />  
<bean id="desk" class="com.example.Desktop" />

Explicit reference

If you explicitly specify a <property> with a ref attribute in a <bean> definition (more in XML-Based Configuration 2 - Dependency Injection (DI) & Wiring), the explicit reference takes precedence over autowiring, even if autowiring is enabled (e.g., autowire="byName" or autowire="byType"). Autowiring is considered only for properties not explicitly defined.

<bean id="person" class="com.example.Person" autowire="byName">
    <property name="computer" ref="lap" />
</bean>
<bean id="lap" class="com.example.Laptop" />
<bean id="computer" class="com.example.Desktop" />
public class Person {  
    // Even though property name matches the bean ID "computer"
    // Spring will not wire Person with the Desktop
    // Since the property computer is explicitly referenced to the Laptop
    Computer computer;  
    
    //...
}

The <property name="computer" ref="lap" /> explicitly specifies that the computer property of the person bean should be wired with the bean having ID "lap" (an instance of Laptop). This overrides the autowire="byName" setting.

Excluding a bean from autowiring

On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the <bean/> element to false.

<bean id="lap" class="com.example.Laptop" autowire-candidate="false"/>

Back to parent page: Spring

Web_and_App_Development Programming_Languages Java Spring_Framework XML_Based_Configuration Dependency_Injection Setter_Injection Autowiring

Reference: