Dependency Injection via XML
Two ways to inject dependencies via XML
- Setter Injection
- Constructor Injection
1. Setter Injection
- Dependencies are injected via setter methods after the bean is instantiated.
- Declared in XML with
propertytag
Setter Injection process:
- Object is created using the default constructor.
- Setter methods are called to inject values or references.
- Default Constructor and Setter method must be specified.
When Using:
- Creates the object(bean).
- Identify the setter method for the property.
- Passes the value (or reference) to the setter and dependency is injected.
Supports
- Attribute or p-schema injection
- Collections (List, Set, Map) injection
- Reference type (other beans) injection
class Address {
private String email;
public void setEmail(String email) { this.email = email; }
}
class Student {
private String name;
private Address address; // Reference type
List<String> fruits; // Collection type
public void setId(int id) { this.id = id; }
public void setName(String name) { this.name = name; }
public void setAddress(Address address) { this.address = address; }
public void setFruits(List<String> fruits) { this.fruits = fruits; }
}
<!-- Attribute or p-schema injection -->
<bean id="addressBean" class="Address" p:email="alamgir.ahosain@gmail.com"/>
<bean id="student1" class="Student">
<property name="name" value="Alamgir"/>
<property name="address" ref="addressBean"/> <!-- Reference type injection -->
<property name="fruits">
<!-- Collections (List) injection -->
<list>
<value>Mango</value>
<value>Jack Fruit</value>
</list>
</property>
</bean>
Scenario
Class Address{}
Class Home{}
Class Student {
private Address address;
public void setAddress(Address address){ this.address = address; }
}
<bean id="address" class="Address"></bean>
<bean id="homeBean" class="Home"></bean>
<bean id="student1" class="Student">
<property name="address" ref="homeBean"/>
</bean>
Question: What happens if a bean’s ref points to another bean with a mismatched type?
Two possible cases:
- Bean not found : throws
NoSuchBeanDefinitionException - Bean type mismatch : throws
BeanCreationException
Question:
- Is it possible to create bean object or not? → YES
- Is it possible to do Setter Injection, Constructor Injection or both? → NO
2. Constructor Injection
- Constructor Injection provided via the class constructor.
- Object Creation and Injection happen at the same time.
- Constructor must be specified.
Constructor Injection Process:
- Object is created via a constructor with arguments (No need setters).
- Values or bean references are passed directly through the constructor.
Ambiguity arises when multiple constructors exist with same argument types.
Fix using :
- index : specify parameter position
- type : specify parameter type
- name : specify parameter name
<!-- 1. Use index(parameter position (0, 1, 2 …).) -->
<bean id="student" class="Student">
<constructor-arg index="0" value="Alamgir"/> <!-- String first -->
<constructor-arg index="1" value="12"/> <!-- int second -->
</bean>
<!-- 2. Use type( parameter data type.) -->
<bean id="student" class="Student">
<constructor-arg type="String" value="Alamgir"/>
<constructor-arg type="int" value="12"/>
</bean>
<!-- 3. Use name(if compiled with parameter) (specify parameter name) -->
<bean id="student" class="Student">
<constructor-arg name="name" value="Alamgir"/>
<constructor-arg name="id" value="12"/>
</bean>
3. Bean Wiring
- Connecting one bean to another bean.
- Done by using the ref attribute.
<bean id="addressBean" class="Address"></bean>
<bean id="student" class="Student">
<property name="address" ref="addressBean"/>
</bean>
4. Autowiring Modes
Allows to automatically inject dependent beans without explicitly using the ref attribute.
Four configuration values for `autowire` attribute:
-
no : manual wiring only, no automatic injection.
-
byType
- Matches bean by class type.
- Uses setter injection by default.
- Constructor injection is not used unless explicitly with
@Autowired. - Setter required, Constructor not used.
- Bean ID not used.
Situtation when:
- No bean of the type → throws
NoSuchBeanDefinitionException. - Exactly one bean of the type → injects successfully.
- More than one bean of the type → throws
NoUniqueBeanDefinitionException.
-
byName
- Matches property name with bean ID.
- Type doesn’t matter.
- Setter required,, Constructor not used.
- Bean ID is used.
Situtation when:
- No bean with matching name → throws
NoSuchBeanDefinitionException. - Exactly one bean with matching name → injects successfully.
- Duplicate bean names → Duplicate bean definition throws
BeanDefinitionStoreException.
-
constructor
- Matches constructor argument type with bean ID.
-
Works only with constructors.
Situtation when:
-
No bean of the type →
NoSuchBeanDefinitionException. - Exactly one bean of the type → injects successfully.
- If more than one bean of type exist → tries to match constructor parameter name with bean ID.If found then
injectsotherwise throwsNoUniqueBeanDefinitionException.
Scenario
class Address {
private String name;
public Address() {}
public Address(String name){ this.name=name; }
public void setName(String name){ this.name=name; }
}
class Student {
private Address addressBean;
public Student() {}
public Student(Address addressBean){ this.addressBean=addressBean; }
public void setAddressBean(Address addressBean){ this.addressBean=addressBean; }
}
byType
( property name addressBean is type of Address (Address in Student))
<bean id="aBean" class="Address">
<property name="name" value="Alamgir"/>
</bean>
<bean id="studentBean" class="Student" autowire="byType"/>
byName
(property name addressBean = bean ID addressBean)
<bean id="addressBean" class="Address">
<property name="name" value="Alamgir"/>
</bean>
<bean id="studentBean" class="Student" autowire="byName"/>
constructor
<bean id="addressBean" class="Address">
<property name="name" value="Alamgir"/>
</bean>
<bean id="studentBean" class="Student" autowire="constructor"/>
Steps:
- Finds the
Student(Address addressBean)constructor. - Looks for a bean of type
Address. - Injects it automatically.
5. When to Use Setter and Constructor Injection
Use Setter Injection when:
- Dependencies are optional (object can be created without them).
- To set partial/optional properties.
- Properties may change or override later (mutable).
- Easier config when many properties.
Use Constructor Injection when:
- Dependencies are mandatory (object cannot exist without them).
- To set all/mandatory properties at once.
- Object should be immutable after creation.
- Ensures required dependencies at object creation time.
Github Code : Dependency Injection Basic : spring
Github Code : Autowiring : spring