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:

  1. Reads the bean definitions in XML or annotations.
  2. Identifies the constructor with the required arguments.
  3. Resolves the arguments from the configuration (value, ref)
  4. 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 or name. They are defined inline and cannot be referenced elsewhere in the configuration.
  • 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: