Cyclic dependency is the one of the major limitation of the Injection process in Spring. Constructor Injection has chance of having Cyclic Dependency, while the same is not possible in case of Setter Injection.
When both the beans depends on each other for injecting the bean property then it forms the Cyclic Dependency. In Cyclic Dependency containers goes on infinite loop for getting the bean instance, so to avoid this type of situation ( Cyclic Chaining ) it finally create the instance of second bean by calling default constructor. So as a result only one bean will be injected and another remain uninjected.
To better understand the above statement lets take an example :
There are two bean A and B and both depends on each other.
Case 1: With Constructor Injection
A.java
public class A {
B b; // Bean property
public A(B b) {
this.b = b; // Constructor Injection
}
}
B.java
public class B {
A a; // Bean property
public B(A a) {
this.a = a; // Constructor Injection
}
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("Spring-Core.xml");
Hello hello = (Hello)ctx.getBean("hello");
}
}
Spring-Core.java
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="a" class="com.def.A" autowire="constructor">
</bean>
<bean id="b" class="com.def.B" autowire="constructor">
</bean>
</beans>
Explanation:
1. Read the first bean tag in XML file and found one dependencies of bean B.
2. Try to get the instance of bean B but not running in the Spring Container.
3. Try to create the instance by reading the bean definition of B.
4. But again found the dependency of A on B.
5. Now Container try to get the instance of bean A ( Which already have dependency ) .
6. Like this it will form infinite loop and at last one bean will be injected by avoiding the Cyclic chaining.
Note: This happens all because in case of Constructor Injection
1. Container first inject the dependencies.
2. Then create the instance of the current bean.
So in the above condition it both the bean cannot be injected and hence non of the instance will be created and hence form the Cyclic Dependency but to avoid Cyclic dependencies , container create the instance of second bean by calling the default constructor.
Case 2: With Setter Injection
A.java
public class A {
B b; // Bean property
public setA(B b) {
this.b = b; // Constructor Injection
}
}
B.java
public class B {
A a; // Bean property
public setB(A a) {
this.a = a; // Constructor Injection
}
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("Spring-Core.xml");
Hello hello = (Hello)ctx.getBean("hello");
}
}
Spring-Core.java
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="a" class="com.def.A" autowire="byType">
</bean>
<bean id="b" class="com.def.B" autowire="byType">
</bean>
</beans>
Explanation:
1. Read the first bean tag in XML file and found one dependencies of bean B.
2. Container create the instance of A and try to inject the dependencies.
2. So try to get the instance of bean B to Inject the bean property but not running in the Spring Container.
3. Then try to create the instance by reading the bean definition of B.
4. Again found the dependency of A on B and again before injecting the dependencies on B, first create the instance of B.
5. Now Container try to inject the A's bean property because its instance is available .
6. And finally Instance B is also available and inject the bean property of B.
Note: This happens all because in case of Setter Injection
1. Container first create the instance of the current bean
2. Then Inject the dependencies if any.
So like this no chance of having any Cyclic Dependency in Setter Injection because of creating the current bean instance first, so anyhow a bean instance will be available to inject the bean properties.
0 comments:
Post a Comment