Spring原始碼:Bean初始化過程
阿新 • • 發佈:2019-01-08
主程式碼
bean完成屬性注入之後,接著要以bean進行初始化,初始化過程在AbstractAutowireCapableBeanFactory抽象類中,核心程式碼如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 啟用Aware方法
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 若mbd為null或者mbd不是合成的,執行BeanPostProcessor擴充套件點的PostProcessBeforeInitialization進行修改例項化Bean
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
/* 呼叫Bean的初始化方法,這個初始化方法是在BeanDefinition中通過定義init-method屬性指定的。
** 同時,如果Bean實現了InitializingBean介面,那麼這個Bean的afterPropertiesSet實現也會
** 被呼叫
*/
invokeInitMethods(beanName, wrappedBean, mbd);
if (mbd == null || !mbd.isSynthetic()) {
// 執行BeanPostProcessor擴充套件點的PostProcessAfterInitialization進行修改例項化Bean
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
1. 啟用Aware方法
核心程式碼:
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
BeanNameAware:讓Bean獲取自己在BeanFactory配置中的名字(根據情況是id或者name)
Spring自動呼叫。並且會在Spring自身完成Bean配置之後,且在呼叫任何Bean生命週期回撥(初始化或者銷燬)方法之前就呼叫這個方法。換言之,在程式中使用BeanFactory.getBean(String beanName)之前,Bean的名字就已經設定好了。
BeanClassLoaderAware: 獲取Bean的類裝載器
BeanFactoryAware:讓Bean獲取配置他們的BeanFactory的引用
>
setBeanFactory方法是在根據某個配置檔案建立了一個新工廠之後,Spring才呼叫這個方法,並把BeanFactory注入到Bean中。 讓bean獲取配置自己的工廠之後,可以在Bean中使用這個工廠的getBean()方法,但是,實際上非常不推薦這樣做,因為結果是進一步加大Bean與Spring的耦合,而且,能通過DI注入進來的儘量通過DI來注入。
2. 後處理方法(初始化之前呼叫)
3. 啟用自定義的init方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
// 實現了InitializingBean介面 && (mbd為null || mbd中的afterPropertiesSet方法不是外部方法)
((InitializingBean) bean).afterPropertiesSet();
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
// 呼叫自定義的初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
自定義初始化方法(在配置檔案指定init-method)
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 獲取初始化方法名稱
String initMethodName = mbd.getInitMethodName();
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
// 若指示配置的init方法是是預設方法,且不存在,丟擲異常找不到該方法
throw new BeanDefinitionValidationException(".....");
} else {
// 沒有找到預設的名字叫initMethodName初始化的初始化方法
return;
}
}
ReflectionUtils.makeAccessible(initMethod);
initMethod.invoke(bean);
}