Spring IOC Implementation Principles: Timing of Container and Object Creation

Bean lifecycle

Initialize container

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  • ApplicationContext Yes, it’s  BeanFactory a sub-interface;
  • It refresh()completes  configuration loading, bean registration, and bean instantiation upon startup .
  • This is a preloaded container (Beans are created upon startup).

In contrast  , lazy-loaded containers  create objects BeanFactory only on the first invocation  .getBean()

Parse the configuration and generate BeanDefinition

Spring first reads the configuration file (such as XML or annotations), and parses  <bean> the definitions in the tags, for example:

<bean id="myBean" class="com.example.MyBean" scope="singleton"/>

This information will be encapsulated into  BeanDefinition an object that describes the Bean’s metadata, including:

propertyillustrate
idThe unique name of a bean
classThe fully qualified class name of Bean
scopeScope (singleton / prototype)
constructor args / propertiesDependency information

BeanDefinition It’s not a Bean instance, but a blueprint that tells the container “how to create a Bean”.


Register BeanDefinition

Spring registers all BeanDefinitions in a global registry:

Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
beanDefinitionMap.put("myBean", BeanDefinition@1234);

This step only completes the definition and registration; the object has not yet been instantiated.

When the container starts up ( ApplicationContextor is first accessed  getBean()BeanFactory, Spring begins to actually create objects.
Regardless of how it’s triggered, it ultimately enters the same call chain:

MyBean bean = ctx.getBean("myBean");

getBean()
 └── doGetBean()
      ├── getSingleton()             // Check if it has been created from the cache
      ├── createBean()               // If not created, enter the creation process
      │    ├── createBeanInstance()  // Reflect instantiated object
      │    ├── populateBean()        // Dependency Injection
      │    └── initializeBean()      // Initialize callback
      └── addSingleton()             // Put into cache pool

createBeanInstance(): Creates an object using reflection.

Class<?> clazz = Class.forName(beanDefinition.getBeanClassName());
Object bean = clazz.getDeclaredConstructor().newInstance();
  • Spring uses  reflection  to dynamically create Bean instances;
  • This step only handles instantiation and does not inject dependencies;
  • After the object is created, it is temporarily stored in the cache, waiting for dependency injection.

populateBean(): Performs dependency injection

Spring performs dependency injection based on BeanDefinition or annotation information.
Three common methods are:

Injection methodExampleImplementation
Constructor Injection<constructor-arg>Reflection calls constructor
Setter injection<property>Reflection to call setter methods
Field Injection@Autowired
@Resource
Directly setting field values ​​using reflection

Example:

@Component
public class MyBean {
    @Autowired
    private MyService myService;
}

Underlying reflection logic:

Field field = clazz.getDeclaredField("myService");
field.setAccessible(true);
field.set(bean, context.getBean("myService"));

initializeBean(): Initialization and Callback

After dependency injection is complete, Spring will execute an initialization callback, which includes:

  1. Calling   interfaces such as BeanNameAware, etc.ApplicationContextAware
  2. implement  InitializingBean.afterPropertiesSet();
  3. Call  init-method;
  4. Triggers  BeanPostProcessor(such as AOP proxy enhancement).

addSingleton(): Adds the singleton to the cache.

Once the bean is fully created, Spring will place it in the first-level cache:

singletonObjects.put(beanName, bean);

In this way  getBean("myBean"), subsequent uses will be retrieved directly from the cache instead of being recreated.

Read configuration files or scan annotations
    ↓
Generate Bean Definition
    ↓
 Register to beanDefinitionMap (Definition Registration)
    ↓
Call getBean () or container startup to trigger creation
    ↓
 createBean() → Reflection creates objects
    ↓
 populateBean() → Perform dependency injection
    ↓
 initializeBean() → Initialization and Enhancement
    ↓
 addSingleton() → Cache singleton beans
    ↓
 Return Bean Instance

What are BeanFactory and ApplicantContext?

It can be described as follows: BeanFactory is the “heart” of Spring, and ApplicantContext is the complete “body”.

  • BeanFactory is an infrastructure component of the Spring framework and is designed for Spring itself.
  • ApplicantContext is built on top of BeanFactory and is intended for developers using the Spring framework.

Spring provides many implementations of BeanFactory, the most commonly used being XmlBeanFactory, but it has been deprecated in Spring 3.2. It is recommended to use XmlBeanDefinitionReader or DefaultListableBeanFactory instead.

The BeanFactory interface is located at the top of the class structure tree. Its main method is getBean(String var1), which returns a bean with a specific name from the container.

The functionality of BeanFactory has been continuously expanded through other interfaces. For example, AbstractAutowireCapableBeanFactory defines a method for automatically wiring beans in the container according to certain rules (such as matching by name, matching by type, etc.).

Here’s an example of retrieving beans using an XMLBeanFactory (which is now deprecated):

ApplicationContext  interface

ApplicationContext is derived from BeanFactory and provides more features geared towards real-world applications. You could say that using BeanFactory is like using a manual mode, while using ApplicationContext is like using an automatic mode.

ApplicationContext inherits from the HierarchicalBeanFactory and ListableBeanFactory interfaces. In addition, it extends the functionality of ApplicationContext through other interfaces, including:

  • Bean instantiation/wiring
  • Bean instantiation/chaining
  • Automatic BeanPostProcessor registration
  • Automatic BeanFactoryPostProcessor registration
  • Convenient MessageSource access (i18n)
  • Unlike the lazy loading method of BeanFactory, ApplicationEvent is preloaded, so each bean is instantiated after the ApplicationContext starts.

Here is an example of using ApplicationContext:

ApplicationContext includes all the features of BeanFactory, and it is generally recommended to use the former.