In Spring, beans are the most basic objects and everything is done around them. Spring is a Bean Oriented Programming (BOP) framework. Beans function in BOP much like objects in OOP. Given this importance, we first need to understand what exactly is a Bean?
What is a Bean
First, let’s look at the definition of beans in the Spring documentation:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application
From the above, we can define a Bean: a Bean is an object instantiated, assembled, and managed by IOC.
The life cycle of the Bean
We need to be clear that the life cycle of our Bean here refers primarily to the Singleton Bean. In the case of the Prototype Bean, the IOC container no longer manages the current instance when the user getBean obtains the prototype Bean instance. Instead, the user gets the management, and getBean generates a new instance. For request/session/application/websocket this several scope bean we don’t talk about here.
The Bean life cycle starts at different times in different containers. For ApplicationContext, the bean is instantiated when the container is started. In the case of the BeanFactory, it is not instantiated until the getBean() method is called.
We know that for ordinary Java objects, their life cycle is
- instantiation
- When it is no longer in use, it is collected through the garbage collection mechanism
This is not the case with beans. The Bean life cycle is shown in the following figure
For the above methods, we can divide them into the following categories
The Bean's own methods
Such as constructors, getters/setters, and methods specified by init-method and destory-methodBean-level lifecycle methods
: Can be understood as Bean classes directly implement interface methods, such as BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean, These methods only apply to the current BeanContainer-level methods (BeanPostProcessor series of interfaces)
: after mainly handler method, such as above InstantiationAwareBeanPostProcessor, BeanPostProcessor interface methods. The implementation classes for these interfaces are bean-independent and registered with the Spring container. These post-handlers come into play whenever the Spring container creates any beans.Factory Post-processor approach (BeanFactoryProcessor series of interfaces)
: including AspectJWeavingEnabler, CustomAutowireConfigurer, ConfigurationClassPostProcessor, etc. These are beanFactoryPostProcessors already implemented in the Spring framework to implement specific functionality.
The Bean’s own methods and bean-level lifecycle methods work only on the current Bean, but container-level lifecycle methods and post-factory processor methods work on all beans
1, 2, and 4 are all fairly well understood, so let’s focus on what are BeanPostProcessor and BeanFactoryPostProcessor
In my personal understanding, BeanPostProcessor and BeanFactoryPostProcessor are extension points created by Spring, where users can create their own implementation classes to modify beans or BeanFactory
Note that for the ApplicatonContext, the container can automatically detect and load BeanPostProcessor and BeanFactoryPostProcessor, but the BeanFactory can’t and needs to be registered manually by calling its own methods. There can be more than one BeanPostProcessor and BeanFactoryPostProcessor. ApplicationContext can also according to the org. Springframework. Core. PriorityOrdered and org., springframework. Core. The Ordered for custom sorting, But the BeanFactory can’t. The default order is the order of registration.
Here are two confusing words:
Instantiation
Instantiate, which means invokeThe constructor
InstantiateInitialization
Initialization, as in the Bean’s declaration cycleinit-method
The specified method orInitializingBean.afterPropertiesSet()
methods
Here are some examples of commonly used interfaces:
Common Interfaces
-
BeanNameAware The interface has only one method, setBeanName(String Name), to get the id or name of the bean
-
BeanFactoryAware This interface has only one method, setBeanFactory(BeanFactory BeanFactory), to get the BeanFactory in the current environment
-
ApplicationContextAware This interface has only one method setApplicationContext(ApplicationContext ApplicationContext), To get the ApplicationContext in the current environment
Once you get the IOC container, you can modify the Beans and so on
-
InitializingBean The interface has only one method, afterPropertiesSet(), which is called after property injection is complete
-
DisposableBean This interface has only one method destroy(), called when the container is destroyed, before the user-specified destroy-method
-
BeanPostProcessor This interface has two methods:
- PostProcessBeforeInitialization (Object beans, String beanName) : in
Before initialization
Calling this method - PostProcessAfterInitialization (Object beans, String beanName) : in
After initialization
Calling this method
We know from method signatures that we can use beanName to filter out beans that we need to personalize
- InstantiationAwareBeanPostProcessor class is the BeanPostProcessor interface, commonly used has the following three methods
- PostProcessBeforeInstantiation (Class beanClass, String beanName) : in the bean
Before instantiation
call - PostProcessProperties (PropertyValues PVS, Object Bean, String beanName) : In the bean
After instantiation, before setting properties
call - PostProcessAfterInstantiation (Class beanClass, String beanName) : in the Bean
After instantiation
call
Test the Bean life cycle
Let’s write an example to verify the Bean life cycle we mentioned above
First, we create a new User, which implements our BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean interfaces
Then we implement our own BeanPostProcessor
Implement your own InstantiationAwareBeanPostProcessor
The XML configuration file is as follows
<context:component-scan base-package="com.xiaohuan.springtest"/>
<bean id="user" class="com.xiaohuan.springtest.beanlifecycle.User" init-method="myInit" destroy-method="myDestroy">
<! Constructor injection -->
<constructor-arg index="0" type="int">
<value>1</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>xiaohuan</value>
</constructor-arg>
<! -- setmethod injection -->
<property name="id" value="2"/>
<property name="name" value="dahuan"/>
</bean>
Copy the code
Write our own test classes
Last run project