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:
- Inspects the
person
bean’s properties in the XML configuration. Theperson
bean hasautowire="byName"
, so Spring will attempt to inject dependencies based on the names of thePerson
class’s properties (computer
). - The container also has a bean with ID
"computer"
and typecom.example.Laptop
. - For each property, Spring looks for a bean in the container whose ID matches the property name (
computer
). - 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:
- Inspects the
person
bean’s properties in the XML configuration. Theperson
bean hasautowire="byType"
, so Spring will attempt to inject dependencies based on the type of thePerson
class’s properties (Computer
). - The container has a bean with ID
"lap"
which is of the desired typeComputer
(the laptop class implements theComputer
interface). - For each property, Spring looks for a bean in the container whose type matches the property type (
Computer
). - 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: