Dependency Injection (DI) allows objects to get their required dependencies (other objects or components they need to work) from an external source, instead of creating those dependencies themselves.
- Without DI: An object would use
new
to create the dependencies it needs. - With DI: The object does not create its dependencies. Instead, they are provided (injected) by the Spring IoC container.
You can configure the XML configuration file to tell Spring how to perform the DI. DI exists in two major variants: setter-based injection and constructor-based injection.
Setter injection
Setter Injection in Spring is a type of DI where the Spring IoC container injects dependencies into a bean using its public setter method.
Primitive attribute injection
In this example the IoC container will set the age of the Person
object to 21 upon its creation through the public setAge()
method.
public class Person {
int age;
public void setAge(int age) {
System.out.println("Setter called");
this.age = age;
}
public void getAge() {
System.out.println(age);
}
}
<!-- Bean definitions here -->
<bean id="personBean" class="com.example.Person">
<property name="age" value="21" />
</bean>
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person p1 = (Person) context.getBean("personBean");
p1.getAge();
}
}
Setter called
21
Reference attribute injection (Wiring)
Injecting a reference attribute means setting one bean as a dependency of another bean. The container does this by injecting a reference to another bean, rather than a primitive value (Wiring).
In this example, the Person
class is depend on the Computer
. To support the Spring for dependency injection, you have to have a setter method in the Person
class for Spring to inject the Computer
dependency.
public class Computer {
public void compile() {
System.out.println("The computer is compiling...");
}
}
public class Person {
int age;
Computer computer;
public void setAge(int age) {
this.age = age;
}
public void setComputer(Computer computer) {
System.out.println("Setter called");
this.computer = computer;
}
public void code() {
computer.compile();
System.out.println("Coding...");
}
}
To allow Spring to create a wire between Person
and Computer
. In the XML file, similar to primitive value injection, but instead of value
we use ref
here.
<!-- bean definitions here -->
<bean id="personBean" class="com.example.Person">
<property name="age" value="21" />
<property name="computer" ref="computerBean" />
</bean>
<bean id="computerBean" class="com.example.Computer" />
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person p1 = (Person) context.getBean("personBean");
p1.code();
}
}
Setter called
The computer is compiling...
Coding...
Constructor injection
Constructor Injection is a type of DI where dependencies are provided to a bean via its constructor.
public class Computer {
public void compile() {
System.out.println("The computer is compiling...");
}
}
public class Person {
int age;
Computer computer;
public Person(int age, Computer computer) {
System.out.println("Constructor called");
this.age = age;
this.computer = computer;
}
public void code() {
computer.compile();
System.out.println("Coding...");
}
}
When using constructor injection, Spring:
- Reads the bean definitions in XML or annotations.
- Identifies the constructor with the required arguments.
- Resolves the arguments from the configuration (
value
,ref
) - Calls the constructor to create the bean and injects the dependencies.
<!-- bean definitions here -->
<bean id="personBean" class="com.example.Person">
<constructor-arg name="age" value="25" />
<constructor-arg name="computer" ref="computerBean" />
</bean>
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person p1 = (Person) context.getBean("personBean");
p1.code();
}
}
Constructor called
The computer is compiling...
Coding...
Instead of the name
attribute, you can use the index
attribute in the <constructor-arg>
tag to specify the position of the constructor parameter. The index
specifies the zero-based position of the argument in the constructor’s parameter list.
<bean id="personBean" class="com.example.Person">
<!-- Injects 25 into the first (age) parameter -->
<constructor-arg index="0" value="25" />
<!-- Injects the Computer bean into the second parameter -->
<constructor-arg index="1" ref="computerBean" />
</bean>
<bean id="computerBean" class="com.example.Computer" />
Spring uses the index
attribute to match the arguments with their positions in the constructor.
public class Person {
// ...
// Constructor with parameters in the specified order
public Person(int age, Computer computer) {
this.age = age;
this.computer = computer;
}
// ...
}
Inner bean
An inner bean is a bean definition that is nested inside another bean definition. A <bean/>
element inside the <property/>
or <constructor-arg/>
elements defines an inner bean.
Inner beans are typically used when a bean is only needed as a dependency for another bean.
Characteristics of Inner Beans:
- Scoped to the Containing Bean:
- Inner beans are created and managed exclusively within the scope of the containing (parent) bean. They are not accessible or shared outside the parent bean.
- Anonymous:
- Inner beans do not have a
bean id
orname
. They are defined inline and cannot be referenced elsewhere in the configuration.
- Inner beans do not have a
- Use case
- Inner beans are useful for defining beans that are highly specific to a single parent bean and do not need to be shared across the application.
<bean id="personBean" class="com.example.Person">
<property name="age" value="21" />
<property name="computer">
<bean class="com.example.Computer" />
</ property>
</bean>
public class Person {
int age;
Computer computer;
public void setAge(int age) {
this.age = age;
}
public void setComputer(Computer computer) {
this.computer = computer;
}
}
The Computer
bean is defined inside the Person
bean definition as an inner bean. The Computer
bean will only be created and used within the Person
bean and cannot be accessed elsewhere.
When the Person
bean is created, Spring will also create the inner Computer
bean and inject it into the Person
bean using the setter method.
Back to parent page: Spring
Web_and_App_Development Programming_Languages Java Spring_Framework XML_Based_Configuration Dependency_Injection Setter_Injection Constructor_Injection
Reference: