spring初始化接口InitializingBean

spring初始化接口InitializingBean

InitializingBean接口用於初始化bean。此接口只有一個方法afterPropertiesSet,
繼承此接口的bean,在bean的屬性初始化會執行這個方法。

下面看一下此接口定義

/**
 * 當需要在BeanFactory設置完bean的所有屬性後,還需做一些初始化的操作,可讓該bean實現此接口
 */
public interface InitializingBean {

    /**
     * 由BeanFactory在設置完bean的屬性後調用
     * 該方法可用於實現bean的初始化操作,不過需要在bean的屬性設置完畢後(從名字也可以看出)
     */
    void afterPropertiesSet() throws Exception;

}

我們可以在 AbstractAutowireCapableBeanFactory類中找到此接口的調用位置,如下:


protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
            throws Throwable {

       //是否實現了 InitializingBean 接口
        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("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 {
               // 調用該初始化方法
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }
       // 判斷是否指定了init-method方法
        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) &&
                    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                // 執行init-method 方法
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

spring還有一種初始化方式,指定 init-method 方法,如xml配置的bean

  <bean id="initAndDestroySeqBean" class="com.wthfeng.dubboapi.beans.InitAndDestroyBean" init-method="initMethod"
          destroy-method="destroyMethod"/>

從源碼分析可知,init-method的初始化方法在InitializingBean.afterPropertiesSet 方式之後。

總結如下:

  1. spring有兩種初始化bean的方式,實現InitializingBean接口以及配置init-method方法,兩種方式可以同時使用,實現接口的方式比指定init-method先調用。
  2. 如果調用afterPropertiesSet方法時出錯,則不調用init-method指定的方法。

參考文章

  1. Spring核心接口之InitializingBean
  2. InitializingBean的作用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章