Search code examples
javaspringcircular-dependencyspring-annotationsspring-bean

What's the difference between @Lazy annotation and lazy-init attribute of <bean/> tag?


As per my understanding, @Lazy annotation and lazy-init attribute of tag should have the same functionality. But when I developed the following code, it's showing distinct behaviours. In the following code, I was expecting :- (Circular Dependency Error)

org.springframework.beans.factory.BeanCurrentlyInCreationException

I have attached code using @Lazy annotation, as per my expectations it should not allow Circular Dependency.

@Component
public class A {
   private B b;
   @Autowired
   public A(@Lazy B b) {
         System.out.println("A.A() - 1-param Constructor");
         this.b = b;
   }    
}

@Component
public class B {
   private A a;
   @Autowired
   public B(A a) {
         System.out.println("B.B() - 1-param Constructor");
         this.a = a;
   }        
} 

Main Class :

public class AnnotationApp{
    public static void main(String[] args){
         ApplicationContext ctx = new ClassPathXmlApplicationContext("com/ry/cfgs/annotationAppContext.xml"); 
         B objB = ctx.getBean("b", B.class); 
         A objA = ctx.getBean("a", A.class);
    }
}

Spring Configuration File :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-4.3.xsd">

     <context:component-scan base-package="com.ry.beans.annotation"></context:component-scan>

</beans>

OUTPUT :-

A.A() - 1-param Constructor

B.B() - 1-param Constructor

Require explanation, why it's behaving like this?


Solution

  • From Spring Framework Documentation:

    ... you can also place the @Lazy annotation on injection points marked with @Autowired or @Inject. In this context, it leads to the injection of a lazy-resolution proxy.

    So, in the following code:

    @Autowired
    public A(@Lazy B b) {
        // ...
    }
    

    b will be injected (autowired) on first access instead of on startup.

    Now, if you change your code to the following:

    @Autowired
    public A(@Lazy B b) {
        System.out.println("A.A() - 1-param Constructor");
        System.out.println(b.toString());
        this.b = b;
    }
    

    you will see that org.springframework.beans.factory.BeanCurrentlyInCreationException is thrown.