只要不放棄,希望遲早都會到來!

1. Bean的初始化

如果把bean的生命週期看作一個嬰兒誕生過程的,那麼建立例項相當於嬰兒從母體出來,一絲不掛光禿禿;屬性賦值相當於給寶寶的頭帶帽子,上身穿衣服、下神穿褲子、還有腳丫穿襪子;而初始化相當於教寶寶一些常規的動作,比如給寶寶吸奶,打嗝拍打,哄睡覺等,本篇繼續分析初始化原始碼。

2. 初始化流程概覽

3. 原始碼分析

進入initializeBean方法:

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 啟用aware介面
invokeAwareMethods(beanName, bean);
} Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化前處理的beanPostProcessor , 比如aware介面,InitDestroyBeanPostProcessor,
// ImportAwareBeanPostPorcessor 對ImportAware的支援
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
} try {
// 啟用 init-method方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化後處理的beanPostProcessor
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
} return wrappedBean;
}

看到流程中主要分為上述流程概覽中所述的四個步驟:

step1:啟用aware介面;

step2:初始化前處理的beanPostProcessor;

step3:啟用 init-method方法;

step4:初始化後處理的beanPostProcessor.

下面逐一分析。

啟用aware介面,原始碼如下:

	private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

分別對BeanNameAware、BeanClassLoaderAware、BeanFactoryAwareaware介面進行處理,設定對應的屬性;接下來進入applyBeanPostProcessorsBeforeInitialization方法:

	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

該方法對初始化前的beanPostProcessor進行處理,對比如InitDestroyBeanPostProcessor,對@PostConstruct的支援, ApplicationContextAwareProcessor對某個Aware介面方法的呼叫,ImportAwareBeanPostPorcessor對ImportAware的支援等;

接下來InitializingBean介面和init-method 屬性呼叫對應方法為invokeInitMethods:

	protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable { 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) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 呼叫afterPropertiesSet方法
((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)) {
// 呼叫自定義的init方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}

afterPropertiesSet 和 Init-method 和有@PostConstruct 註解的方法其實核心功能都是一樣的,只是呼叫時序不一樣而已,都是在該類例項化和 IOC 做完後呼叫的,我們可以在這些方法中做一些在 spring 或者 servlet 容器啟動的時候的初始化工作。比如快取預熱,比如快取資料載入到記憶體,比如配置解析,等等初始化工作呼叫順序為先呼叫@PostConstruct(註解使用)、然後是 afterPropertiesSet、InitMethod(xml 配置)方法。

最後一步,初始化後處理的beanPostProcessor,這裡最主要的是完成代理的生成,該內容放到後面AOP階段再深入。

4. 總結

本篇主要分析了bean的初始化相關操作,包括@PostConstruct註解的支援,Aware介面的支援,以及初始化後的afterPropertiesSet方法以及InitMethod方法的支援,最後完成BeanPostProcessor的後置處理,生成aop代理例項,後續將繼續分析FactoryBean介面例項化物件的過程。