Spring Core - How Spring determines bean creation order
Spring manages the creation and initialization of beans within the application context. The order in which beans are created depends on multiple factors, including dependency relationships, bean definitions, and any explicit ordering configurations. Here's how Spring determines the bean creation order:
Dependency Relationships
Spring resolves and creates beans based on their dependencies to ensure that beans are available before they are injected into other beans.
- Constructor Injection: Spring creates beans that are required as constructor arguments before creating the dependent bean.
- Setter/Field Injection: Spring resolves and injects dependencies before calling initialization methods.
- Beans without dependencies can be created in any order unless specified otherwise.
@Component
public class BeanA {
public BeanA() {
System.out.println("BeanA created");
}
}
@Component
public class BeanB {
private final BeanA beanA;
public BeanB(BeanA beanA) {
this.beanA = beanA;
System.out.println("BeanB created");
}
}
Explicit Dependency Declaration with @DependsOn
The @DependsOn annotation allows you to explicitly specify the order in which beans should be created. This is useful when one bean depends on the initialization of another, but the dependency is not directly injected.
@Component
@DependsOn("beanB")
public class BeanC {
public BeanC() {
System.out.println("BeanC created");
}
}
@Component
public class BeanB {
public BeanB() {
System.out.println("BeanB created");
}
}
Using @Order or Ordered Interface
The @Order annotation or the Ordered interface specifies the order in which beans are processed when they are part of a collection or when initializing multiple beans of the same type.
@Component
@Order(2)
public class BeanX {
public BeanX() {
System.out.println("BeanX created");
}
}
@Component
@Order(1)
public class BeanY {
public BeanY() {
System.out.println("BeanY created");
}
}
@Component
public class BeanZ implements Ordered {
@Override
public int getOrder() {
return 3;
}
public BeanZ() {
System.out.println("BeanZ created");
}
}
Bean Factory Post-Processing
If you use a BeanFactoryPostProcessor or BeanDefinitionRegistryPostProcessor, you can programmatically modify the creation order of beans before they are instantiated.
@Component
public class MyPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.getBeanDefinition("beanA").setDependsOn("beanB");
}
}
Lazy Initialization
By default, Spring creates singleton beans eagerly at container startup, since we want to fail fast to detect problems as early as possible. However, you can mark beans as lazy-initialized to defer their creation until they are first accessed.
@Component
@Lazy
public class BeanLazy {
public BeanLazy() {
System.out.println("BeanLazy created");
}
}
Configuration Classes and Method Order
If multiple beans are defined in a @Configuration class, the method definition order in the class matters. Beans are created in the order they are defined in the configuration.
@Configuration
public class AppConfig {
@Bean
public BeanA beanA() {
System.out.println("BeanA created");
return new BeanA();
}
@Bean
public BeanB beanB() {
System.out.println("BeanB created");
return new BeanB();
}
}
Circular Dependencies
- Constructor Injection: Spring throws an error if there’s a circular dependency.
- Setter/Field Injection: Spring can resolve circular dependencies by creating one bean and injecting a reference before the other bean is fully initialized.
@Component
public class Bean1 {
private Bean2 bean2;
@Autowired
public void setBean2(Bean2 bean2) {
this.bean2 = bean2;
}
}
@Component
public class Bean2 {
private Bean1 bean1;
@Autowired
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
}
}
Summary
Spring determines the bean creation order as follows:
- Resolve Dependencies:
- Dependencies are resolved first, ensuring all required beans are created before the dependent bean.
- Explicit Order:
- Use @DependsOn, @Order, or Ordered to define explicit creation order.
- Configuration Order:
- Beans in configuration classes are created in the order of their method definitions.
- Post-Processing:
- Modify bean definitions programmatically using BeanFactoryPostProcessor.
- Lazy Initialization:
- Delay bean creation until it is accessed.
