In this paper, the content
- The full life cycle of a bean
- Lifecycle callback interface
Aware
The interface,
The life cycle of Spring beans
Hot interview question: Can you describe the Spring lifecycle?
Four life cycles
From the source point of view, there are four simple stages: instantiation -> property assignment -> initialization -> destruction
- Instantiate the Instantiation
- Property assignment Populate
- Initialize the Initialization
- Destruction of Destruction
Instantiation and property assignment correspond to the injection of constructor and setter methods, and initialization and destruction are two phases in which users can customize extensions. Interspersed between these four steps are various spring-provided container extension points.
Look at the source code to achieve AbstractAutowireCapableBeanFactory# doCreateBean, has nothing to do with the source code has been omitted, will retain a certain source English comments.
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
// 1 instantiation phase
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 2 Attribute assignment phase
populateBean(beanName, mbd, instanceWrapper);
// 3 Initialization phase
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
return exposedObject;
}
Copy the code
Bean destruction phase source may have a look ConfigurableApplicationContext# close (), each bean will eventually transferred to the DisposableBeanAdapter# destroy () method, which is simpler.
class DisposableBeanAdapter implements DisposableBean.Runnable.Serializable {
@Override
public void destroy(a) {
if (this.invokeDisposableBean) {
try {
// 1 Implement DisposableBean destruction
else {
((DisposableBean) this.bean).destroy(); }}}if (this.destroyMethod ! =null) {
// 2 Custom destruction methods
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName ! =null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if(methodToInvoke ! =null) { invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); }}}}Copy the code
Lifecycle extension points
Spring is powerful because it is easy to extend, and there are many common life-cycle-related extension points. The extension points are divided into 2 types:
-
Enhanced extensions that work on multiple beans
- InstantiationAwareBeanPostProcessor ACTS on the instantiation phase before and after
- BeanPostProcessor is used before and after the initialization phase
- InstantiationAwareBeanPostProcessor role before the destruction phase
-
Enhanced extensions to individual beans
-
Initialization phase
Three Aware interfaces: BeanNameAware BeanClassLoaderAware BeanFactoryAware
InitializingBean interface
Custom initialization method
-
Destruction of phase
DisposableBean interfaces
Custom destruction method
-
Let me draw a summary picture, just to make it clear.
Tip:
BeanNameAware BeanClassLoaderAware BeanFactoryAware is set by calling the corresponding interface method during initialization; Other Aware interfaces are as follows EnvironmentAware, EmbeddedValueResolverAware, ApplicationContextAware (ResourceLoaderAware \ ApplicationEventPublisherAware \ M EssageSourceAware) is in front of the initialization through BeanPostProcessor# postProcessBeforeInitialization () to call the corresponding interface Settings.
I’ll go deeper when I have a chance to write Spring source code later.
Bean life cycle callback
In Spring Series 2: Basic Concepts and Usage of Spring containers:
I highly recommend reading the comments on the BeanFactory source code, which are very detailed and common interview questions: Describe the Spring lifecycle? There’s a very official full explanation in the notes
To be precise, the following source code comments are full life cycle callbacks, limited to the bean’s initialization and destruction phases. The full bean life cycle is analyzed in the next section.
The complete call process during initialization is as follows:
Container management of the bean lifecycle provides a lifecycle interface that allows developers to customize bean lifecycle operations such as initialization and destruction.
The bean initializes three callbacks
Spring provides three ways to initialize a bean’s callback:
-
InitializingBean interface
Org. Springframework. Beans. Factory. Set up a bean InitializingBean interface beans in the container to perform all the necessary attributes after initialization. The downside of this approach is that the Spirng container is coupled to the class.
-
The
in XML specifies the init-method method <bean class="com.crab.spring.ioc.demo11.BeanOne" id="beanOne" init-method="myInit"/> Copy the code
-
Use the @postconstruct annotation
Now that there are three, the question arises:
- Using three methods at once, specifying three different methods, what is the order of execution?
- How many times do you execute the same method, 3 times?
Directly through the case to verify.
Case 1:3 ways 3 different ways
The definition of a class
public class BeanOne implements InitializingBean {
// 1 How to implement the interface
@Override
public void afterPropertiesSet(a) throws Exception {
System.out.println("BeanOne InitializingBean afterPropertiesSet");
}
// Use XML init-method to configure
public void myInit(a) {
System.out.println("BeanOne init-method myInit");
}
@PostConstruct
public void postConstruct(a) {
System.out.println("BeanOne PostConstruct postConstruct"); }}Copy the code
Bean information is defined as an XML configuration file
<? xml version="1.0" encoding="UTF-8"? > <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <! -- Scans the bean under the specified package and automatically DI--> <context:annotation-config/> <beanclass="com.crab.spring.ioc.demo11.BeanOne" id="beanOne" init-method="myInit"/>
</beans>
Copy the code
Run the test
@org.junit.Test
public void test1(a) {
System.out.println(Start initializing the container);
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo11/spring.xml");
System.out.println("Container in use ----");
BeanOne beanOne = context.getBean(BeanOne.class);
System.out.println(beanOne);
System.out.println("Begin destroying containers.");
context.close();
System.out.println("End of container destruction.");
}
Copy the code
The test results
BeanOne PostConstruct PostConstruct BeanOne InitializingBean afterPropertiesSet BeanOne init-method myInit Containers in use -- com. Crab. Spring. The ioc. Demo11. BeanOne@f0f2775Start Destroying containers End destroying containersCopy the code
Conclusion: @postconstruct > InitializingBean > XML init-method
Case 2:3 ways to specify the same method
The class definition is as follows
public class BeanTwo implements InitializingBean {
// 1 How to implement the interface
// 2 Use XML init-method for configuration
// 3 Annotation mode
@PostConstruct
@Override
public void afterPropertiesSet(a) throws Exception {
System.out.println("BeanTwo InitializingBean afterPropertiesSet"); }}Copy the code
The XML configuration file and test program are similar and not duplicated.
The result is as follows
To initialize container BeanTwo InitializingBean afterPropertiesSet containers in use -- com. Crab. Spring. The ioc. Demo11. BeanTwo @ 3 f200884 began to destroy container end the destruction of the containerCopy the code
Conclusion: Three ways to specify the same method, will only be called once, not repeatedly
Consider: a class with two @postConstruct annotations init1() and init2(). Which one does the callback initialize?
Bean’s destruction callback
Like initialization callbacks, Spring provides three ways to do bean destruction callbacks:
- Implement the DisposableBean interface
- Destroy-method is configured in XML
- Using the @ PreDestroy
Similar to the order and times of execution conclusion:
- Three methods To specify three different methods, callback order: @predestroy > DisposableBean > Destroy-method is configured in XML
- The same method is specified in three ways, and the callback is only once
Integrated case
Define the class
public class BeanThree implements DisposableBean {
// Approach 1 to DisposableBean
@Override
public void destroy(a) throws Exception {
System.out.println("BeanThree DisposableBean destroy");
}
// Configure destroy-method in mode 2 XML
public void destroy2(a){
System.out.println("BeanThree destroy-method destroy3");
}
// Approach 3 uses the @predestroy annotation
@PreDestroy
public void destroy3(a){
System.out.println("BeanThree @PreDestroy destroy3"); }}Copy the code
Configure the destruction callback in XML
<! -- Scan beans under specified package and automatically DI-->
<context:annotation-config/>
<bean class="com.crab.spring.ioc.demo11.BeanThree" destroy-method="destroy2"/>
Copy the code
Test procedures and results
@org.junit.Test
public void test3(a) {
System.out.println(Start initializing the container);
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo11/spring3.xml");
System.out.println("Container in use ----");
BeanThree beanOne = context.getBean(BeanThree.class);
System.out.println(beanOne);
System.out.println("Begin destroying containers.");
context.close();
System.out.println("End of container destruction.");
}
// The results are compared with the conclusionsTo initialize container vessel in use -- com. Crab. Spring. The ioc. Demo11. BeanThree@f0f2775Begin destroying the container BeanThree@PreDestroyDestroy3 BeanThree DisposableBean destroy BeanThree destroy-method Destroy3 End destroy the containerCopy the code
Think about it: how do YOU configure the default initialization and destruction callback methods globally in an XML configuration, rather than on every bean? default-init-method default-destroy-method
Aware
The interface,
The principle of analytic
Aware is a tag superinterface, and Spring provides an extensive implementation of the Aware callback interface that lets beans fetch the specific infrastructure dependencies they need from the container.
public interface Aware {}
Copy the code
Take a look at the ApplicationContextAware interface
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
Copy the code
When the ApplicationContext to create an implementation org. Springframework. Context. The ApplicationContextAware interface object instance, A reference to the ApplicationContext is provided for the instance. Go straight to the case.
Define a class to implement ApplicationContextAware
public class BeanFour implements ApplicationContextAware {
// The container object ApplicationContext used to get the initial class object
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
public ApplicationContext getContext(a) {
returncontext; }}@Configuration
@ComponentScan
public class AppConfig {}Copy the code
Test procedures and results
@org.junit.Test
public void test_aware(a) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
BeanFour bean = context.getBean(BeanFour.class);
System.out.println(bean.getContext() == context);
context.close();
}
/ / the result
true
Copy the code
As a result, the BeanFour instance has retrieved the container object that created it.
The main purpose of using the Aware interface is to capture the underlying objects related to the container, namely dependency injection, but the downside is that it strongly couples the application classes to Spring. On the other hand, dependency injection is also possible via @AutoWired, with lower coupling.
@Component
public class BeanFour2 {
// The container object ApplicationContext used to get the initial class object
@Autowired
private ApplicationContext context;
public ApplicationContext getContext(a) {
returncontext; }}Copy the code
Aware
Interface summary
Spring provides an extensive Aware callback interface that lets beans indicate to containers that they need specific infrastructure dependencies, as shown in the following table. As a general rule, the name indicates the dependency type.
The interface name |
---|
ApplicationContextAware |
ApplicationEventPublisherAware |
BeanClassLoaderAware |
BeanFactoryAware |
BeanNameAware |
LoadTimeWeaverAware |
MessageSourceAware |
NotificationPublisherAware |
ResourceLoaderAware |
conclusion
This article introduces the full lifecycle of various beans, lifecycle callback interfaces, and Aware interfaces.
This source code address: github.com/kongxubihai…
Knowledge sharing, reproduced please indicate the source. Learning has no priority, the first!