DEV Community

javatute673
javatute673

Posted on

How to use @Lazy annotation in case of Circular Dependency

Using the @Lazy annotation in Spring is a common technique to resolve circular dependencies. Circular dependencies occur when two beans are dependent on each other, leading to a situation where neither bean can be instantiated without the other already existing.

To understand how @Lazy helps, let's first look at what a circular dependency might look like and then how to resolve it with @Lazy.

Circular Dependency Example

Suppose you have two classes, ClassA and ClassB, and they depend on each other.

@Component
public class ClassA {
    private final ClassB classB;

    @Autowired
    public ClassA(ClassB classB) {
        this.classB = classB;
    }
}

@Component
public class ClassB {
    private final ClassA classA;

    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }
}
Enter fullscreen mode Exit fullscreen mode

In this scenario, Spring cannot instantiate ClassA without first instantiating ClassB and vice versa, leading to a circular dependency problem.

Resolving with @Lazy

You can resolve this by using the @Lazy annotation. @Lazy defers the initialization of a bean until it is actually needed. This can break the circular dependency as one of the beans will not be fully initialized (i.e., its dependencies won't be injected) until it's first used.

@Component
public class ClassA {
    private final ClassB classB;

    @Autowired
    public ClassA(@Lazy ClassB classB) {
        this.classB = classB;
    }
}

@Component
public class ClassB {
    private final ClassA classA;

    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }
}
Enter fullscreen mode Exit fullscreen mode

In this modified example, ClassA's dependency on ClassB is marked as @Lazy. When Spring creates an instance of ClassA, it injects a lazy proxy for ClassB instead of an actual instance of ClassB. The actual ClassB instance is not created until a method on the ClassB proxy is called. This delay breaks the circular dependency chain and allows Spring to successfully create both beans.

Things to Note

  1. Design Smell: Circular dependencies often indicate a potential flaw in the design of your application. It's generally a good idea to revisit your design and consider refactoring to eliminate circular dependencies altogether.

  2. Proxy Behavior: With @Lazy, Spring creates a proxy to inject as the dependency. This means that the actual bean will be created when the proxy is first accessed. Be aware of this lazy behavior as it might have implications for your application logic.

  3. Alternative Solutions: Other than using @Lazy, you can also resolve circular dependencies by using setter injection or method injection, which allows one of the beans to be constructed without needing the other to be fully initialized.

Using @Lazy is a quick workaround for circular dependencies, but it's important to consider whether a redesign of the application's components and their relationships might be a more sustainable solution.

Top comments (0)