For normal Java objects, the object is created when new and collected by the garbage collection mechanism when it has no references. Objects hosted by the Spring IoC container, on the other hand, have their life cycles completely controlled by the container.

Bean life cycle process

1. Instantiate the Bean

For BeanFactory containers, createBean is called when a customer requests an uninitialized Bean from the container, or when another uninitialized dependency needs to be injected to initialize the Bean.

For the ApplicationContext container, all beans are instantiated when the container is started.

The container is instantiated by getting information from the BeanDefinition object. And this step is just a simple instantiation without dependency injection. The instantiation object is wrapped in a BeanWrapper object, which provides an interface to set the properties of the object, avoiding the need for reflection to set the properties.

2. Set object properties (dependency injection)

The instantiated object is wrapped in a BeanWrapper object and is still in its native state without dependency injection. Next, Spring does dependency injection based on the information in the BeanDefinition. Dependency injection is also done through the interface provided with BeanWrapper to set properties.

3. Inject Aware interface

Spring then detects whether the object implements the xxxAware interface and injects the associated xxxAware instance into the bean.

  • If the Bean implements the BeanNameAware interface, its implemented setBeanName(String beanId) method is called, passing in the Bean’S ID from the Spring configuration file
  • If the Bean implements the BeanFactoryAware interface, its implementation of setBeanFactory() is called, passing in the Spring factory itself (you can use this method to retrieve other beans).
  • If the Bean implements the ApplicationContextAware interface, the setApplicationContext(ApplicationContext) method is called, passing in the Spring context, ApplicationContext is a subinterface of the BeanFactory and has more implementation methods

4.BeanPostProcessor

After the above steps, the bean object is constructed correctly, but if you want some custom processing before the object is used, you can do it through the BeanPostProcessor interface.

This interface provides two functions:

  • postProcessBeforeInitialzation( Object bean, String beanName )

The currently initializing bean object is passed in, and we can do anything with the bean. This function is executed before the InitialzationBean and is therefore called pre-processing. All Aware interface injection is done in this step.

  • postProcessAfterInitialzation( Object bean, String beanName )

The currently initializing bean object is passed in, and we can do anything with the bean. This function is executed after InitialzationBean completes and is therefore called post-processing.

5. InitializingBean and init – method

This stage is entered when the BeanPostProcessor’s pre-processing is complete.

The InitializingBean interface has only one function:

  • afterPropertiesSet()

This stage can also add our custom logic before the bean is formally constructed, but unlike pre-processing, because the function does not pass in the current bean object, there is no way to process the object itself at this stage, only to add some additional logic. To use it, we need to have the bean implement the interface and write the added logic in the function. Spring then checks if the current bean implements the interface after the pre-processing is complete and executes the afterPropertiesSet function.

Of course, Spring, to make it less intrusive to the client code, provides the bean configuration with the init-method property, which specifies the name of the function that needs to be executed at this stage. Spring executes the function we set up during initialization. Init-method essentially still uses the InitializingBean interface.

6. DisposableBean and destroy – method

As with init-method, you can execute the specified logic before the bean is destroyed by specifying a function for destroy-method.

Code sample

Annotation way

package com.easy.bean; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @component @slf4j public class AnnotationBean {@postconstruct public void start() {log.info("AnnotationBean starts initialization "); } @predestroy public void destroy() {log.info("AnnotationBean starts to destroy "); }}Copy the code

InitializingBean and DisposableBean interfaces

package com.easy.bean; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Service; @Service @Slf4j public class SpringLifeCycleService implements InitializingBean, DisposableBean {@override public void afterPropertiesSet() throws Exception {log.info("SpringLifeCycleService start "); } @override public void destroy() throws Exception {log.info("SpringLifeCycleService destroy "); }}Copy the code

Custom initialization and destruction methods

package com.easy.bean; import lombok.extern.slf4j.Slf4j; @slf4j public class SpringLifeCycle {public void start() {log.info("SpringLifeCycle starts initialization "); } public void destroy() {log.info("SpringLifeCycle starts destroying "); }}Copy the code

Configuration to add

package com.easy.bean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class LifeCycleConfig { @Bean(initMethod = "start", destroyMethod = "destroy") public SpringLifeCycle create() { SpringLifeCycle springLifeCycle = new SpringLifeCycle(); return springLifeCycle; }}Copy the code

Or the XML configuration is as follows

<bean class="com.easy.bean.SpringLifeCycle" init-method="start" destroy-method="destroy"></bean>Copy the code

Implement xxxAware interface

package com.easy.bean; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component @Slf4j public class SpringLifeCycleAware implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; The info (SpringLifeCycleAware "start"); }}Copy the code

The setApplicationContext method is then called in the springLifeCycleAware bean initialization and the applicationContext object is obtained.

BeanPostProcessor enhances the processor

Implementation of BeanPostProcessor interface, all beans in Spring when doing initialization will call two methods in the interface, can be used for some special bean processing

package com.easy.bean; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @component@slf4j public class SpringLifeCycleProcessor implements BeanPostProcessor {/** * @param is called before initialization bean * @param beanName * @return * @throws BeansException */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("annotationBean".equals(beanName)) { log.info("SpringLifeCycleProcessor BeanName ={}", beanName); } return bean; ** @param bean * @param beanName * @return * @throws BeansException */ @override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("annotationBean".equals(beanName)) { log.info("SpringLifeCycleProcessor BeanName ={}", beanName); } return bean; }}Copy the code

Run the sample to see the console output

The 2020-01-09 17:46:37. 9544-022 the INFO [main] O.A.C.C.C. [Tomcat]. [localhost]. / / : Initializing Spring Embedded WebApplicationContext 2020-01-09 17:46:37.023 INFO 9544 -- [main] o.s.web.context.ContextLoader : Root WebApplicationContext: Initialization completed in 1642, the 2020-01-09 ms 17:46:37. 081 INFO 9544 - [the main] com. Easy. Beans. SpringLifeCycleProcessor : SpringLifeCycleProcessor starts to initialize beanName=annotationBean 2020-01-09 17:46:37.089 INFO 9544 -- [main] com.easy.bean.AnnotationBean : AnnotationBean began to initialize the 2020-01-09 17:46:37. 089 INFO 9544 - [the main] com. Easy. Beans. SpringLifeCycleProcessor: BeanName =annotationBean 2020-01-09 17:46:37.090 INFO 9544 -- [main] com.easy.bean.SpringLifeCycleAware : SpringLifeCycleAware started the 2020-01-09 17:46:37. 091 INFO 9544 - [the main] com. Easy. Beans. SpringLifeCycleService: SpringLifeCycleService started the 2020-01-09 17:46:37. 093 INFO 9544 - [the main] com. Easy. Beans. SpringLifeCycle: SpringLifeCycle began to initialize the 17:46:37 2020-01-09. 9544-279 the INFO [main] O.S.S.C oncurrent. ThreadPoolTaskExecutor: Initializing ExecutorService 'applicationTaskExecutor'Copy the code

data

  • Bean life cycle sample source code
  • The official documentation
  • The resources

Spring Boot and Cloud learning projects