In the previous article, we looked at step 5 in doCreateBean() : property population in detail, and this article continues with step 6 in doCreateBean() : initializing the bean instance object
This article is transferred from the public number: impression channel source
Let’s review the main flow of CreateBean:
- If it is singleton mode, get the BeanWrapper instance object from the factoryBeanInstanceCache cache and remove the cache
- call
createBeanInstance()
Instantiate the bean - Post processing
- Singleton pattern for loop dependency processing
- fill
- Initialize the bean instance object
- Depend on the check
- Register the bean’s destruction method
1. Initialization
After filling the Bean with properties, Spring initializes the Bean as follows:
//AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// The JDK's security mechanism validates permissions
if(System.getSecurityManager() ! =null) {
// <1> Activate the Aware method to handle special beans: Aware, BeanClassLoaderAware, BeanFactoryAware
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// <1> Activate the Aware method to handle special beans: Aware, BeanClassLoaderAware, BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// <2> postprocessor, before
if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }// <3> Activate the user-defined init method
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// <2> after
if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }return wrappedBean;
}
Copy the code
The method of initializing the bean is actually three steps, and these three steps are mainly initialized according to user Settings. These three steps are:
-
<1> Activate the Aware method.
-
<2> Rear processor.
-
<3> Custom init method.
1.1, Aware
Aware, English translation is Aware of, Aware of. Spring provides a number of Aware interfaces to assist Spring beans in programmatically calling the Spring container, and you can enhance the functionality of Spring beans by implementing these interfaces.
Spring provides the following series of Aware interfaces:
LoadTimeWeaverAware: the Spring Bean is loaded into a third party module, such as AspectJ BeanClassLoaderAware: the Spring Bean is loaded into the class loader BootstrapContextAware: Resource adapter BootstrapContext, such as JCA and CCI ResourceLoaderAware: the loader that accesses resources at the bottom level BeanFactoryAware: declares BeanFactory PortletConfigAware: PortletConfig PortletContextAware: PortletContext ServletConfigAware: ServletConfig ServletContextAware: ServletContext MessageSourceAware: internationalization ApplicationEventPublisherAware: application events NotificationPublisherAware: JMX notifies BeanNameAware: Declare the name of the Spring Bean
Aware is quite complicated, and I will study this content in the future. I won’t talk more about it here.
1.2. Rear processor
BeanPostProcessor, encountered several times in the previous bean loading process, is used to: If we want to add some of our own logic after the Spring container completes Bean instantiation, configuration, and other initialization, use this interface, which gives the user ample authority to change or extend Spring. Is an essential interface for our extension and enhancement of Spring.
ApplyBeanPostProcessorsBeforeInitialization () method, the code is as follows:
// AbstractAutowireCapableBeanFactory.java
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// Iterate through the BeanPostProcessor array
for (BeanPostProcessor processor : getBeanPostProcessors()) {
/ / processing
Object current = processor.postProcessBeforeInitialization(result, beanName);
// Return null, return result
if (current == null) {
return result;
}
/ / change the result
result = current;
}
return result;
}
Copy the code
ApplyBeanPostProcessorsAfterInitialization () method, the code is as follows:
// AbstractAutowireCapableBeanFactory.java
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
/ / traverse BeanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
/ / processing
Object current = processor.postProcessAfterInitialization(result, beanName);
// Return null, return result
if (current == null) {
return result;
}
/ / change the result
result = current;
}
return result;
}
Copy the code
The logic is to get the defined BeanPostProcessor using the getBeanPostProcessors() method, Then call its respectively postProcessBeforeInitialization () and postProcessAfterInitialization () method, customized business process.
1.3. Customize init methods
The configuration of a < bean > tag in XML, init-method, allows us to perform some of our own custom logic when the bean is initialized. This is where it is triggered, with the following code:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// If InitializingBean is an InitializingBean, afterPropertiesSet() is called.
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null| |! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if(System.getSecurityManager() ! =null) { // Safe mode
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
// <1> property initialization processing
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throwpae.getException(); }}else {
// <1> property initialization processing((InitializingBean) bean).afterPropertiesSet(); }}if(mbd ! =null&& bean.getClass() ! = NullBean.class) { String initMethodName = mbd.getInitMethodName();if(StringUtils.hasLength(initMethodName) && ! (isInitializingBean &&"afterPropertiesSet".equals(initMethodName)) && ! mbd.isExternallyManagedInitMethod(initMethodName)) {// <2> Activates the user-defined initialization methodinvokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code
First, check if it is InitializingBean. If so, you need to execute the afterPropertiesSet() method, because in addition to customizing the initialization method with init-method, you can also implement the InitializingBean interface. The interface has only one afterPropertiesSet() method. <1> #afterPropertiesSet() method followed by <2> init-method.