1. 程式人生 > >Spring原始碼:Bean初始化過程

Spring原始碼:Bean初始化過程

主程式碼

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);
}

4. 後處理方法(初始化之後呼叫)