Spring - Controlling Beans Loading Order, using @DependsOn

[Updated: Sep 5, 2016, Created: Dec 9, 2015]

The order in which Spring container loads beans cannot be predicted. There's no specific ordering logic specification given by Spring framework. But Spring guarantees if a bean A has dependency of B (Bean A has an instance variable @Autowired B b; for example) then B will be initialized first. But what if bean A doesn't have direct dependency of B but we still want B to initialize first.



When we want to control beans initializing order

There might be scenarios where A is depending on B indirectly. May be B is supposed to update some global cache outside of B, may be via a singleton pattern and cache is not registered with the Spring container and A is using that cache. Then of course A doesn't want to access the cache if it's not ready. Another scenario: may be A is some sort of events publisher (Or JMS publisher) and B (or may be more beans) are listening to those events. This is a typical scenario of observer pattern. Again, we don't want B to miss any events and would like to have B being initialize first.

In short, there could be many situations where we want B to initialize before A to avoid some kind of side effects. There we should use @DependsOn annotation on A indicating to the container that B should be initialize first. Here's an example to demonstrate how that works.




Example Projects


Example Project

Dependencies and Technologies Used :

  • Spring Context 4.2.3.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.0.4

Spring Depends On Example Select All Download
  • spring-depends-on
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • bean

On Running AppConfig main method. We will get this output.

EventListenerBean initializing
EventPublisherBean initializing
event received in EventListenerBean : event published from EventPublisherBean

Now if in AppConfig, we comment out @DependsOn from eventPublisherBean(), we might or might not get the same output. On running main method multiple times, occasionally we will see that EventListenerBean doesn't receive event all the time (I'm using JDK 1.8 and Spring 4.2.3). Why occasionally? Why not always? Because during container start up, Spring can load beans in any order. There's one way to be 100% sure of the difference of not using @DependsOn: use @Lazy on eventListenerBean() method:

package com.logicbig.example.app;

import com.logicbig.example.bean.EventListenerBean;
import com.logicbig.example.bean.EventPublisherBean;
import org.springframework.context.annotation.*;

@Configuration
public class AppConfig {

    @Bean(initMethod = "initialize")
    //  @DependsOn("eventListener")
    public EventPublisherBean eventPublisherBean() {
        return new EventPublisherBean();
    }

    @Bean(name = "eventListener", initMethod = "initialize")
    @Lazy
    public EventListenerBean eventListenerBean() {
        return new EventListenerBean();
    }

    public static void main(String... strings) {
        new AnnotationConfigApplicationContext(AppConfig.class);
    }
}

That would cause EventListenerBean not to load during start up but when it is used by some other bean. This time we will see that only EventPublisherBean is initialized by the container:

EventPublisherBean initializing

Now put back @DependsOn and don't remove @Lazy as well, we will get the output we saw first time. Even though we are using @Lazy, eventListenerBean is still being loaded during start up because of @DependsOn referencing of EventPublisherBean.

See Also