首先咱們來看一下InitializingBean接口,發現它只有一個方法,因此實現該接口只需實現這個方法就能夠了。java
package org.springframework.beans.factory; public interface InitializingBean { void afterPropertiesSet() throws Exception; }
咱們來定義一個service實現該接口,測試一下該接口提供的初始化功能,同時與init-method配置的初始化方法進行比較。web
public class PlatformxService implements InitializingBean{ @Override public void afterPropertiesSet() throws Exception { System.out.println("初始化執行:afterPropertiesSet"); } public void initMethod(){ System.out.println("初始化執行:initMethod"); } }
在配置文件中進行該service配置spring
<bean id="platformxService" class="com.sfpay.platformx.service.PlatformxService" init-method="initMethod" />
由於我搭建的是web工程,這裏啓動容器觀察初始化方法執行順序apache
初始化執行:afterPropertiesSet 初始化執行:initMethod
這裏咱們能夠看到在spring初始化bean的時候,afterPropertiesSet方法執行再前,initMethod方法執行在後,爲何會出現這種狀況呢?咱們就進一步看一下spring加載bean時候的源碼。在AbstractAutowireCapableBeanFactory中咱們能夠找到spring調用bean初始化方法的代碼。框架
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { //判斷bean是否實現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(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { //直接經過bean調用afterPropertiesSet方法 ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ////直接經過bean調用afterPropertiesSet方法 ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { //判斷是否有配置init-method方法 String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //在該方法中調用init-method配置方法 invokeCustomInitMethod(beanName, bean, mbd); } } }
咱們再進入到invokeCustomInitMethod方法中查看,init-method配置初始化方法調用過程ide
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()) { throw new BeanDefinitionValidationException("Couldn't find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'"); } else { if (logger.isDebugEnabled()) { logger.debug("No default init method named '" + initMethodName + "' found on bean with name '" + beanName + "'"); } // Ignore non-existent default lifecycle methods. return; } } if (logger.isDebugEnabled()) { logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { ReflectionUtils.makeAccessible(initMethod); return null; } }); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { //經過反射調用初始化方法 initMethod.invoke(bean); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { InvocationTargetException ex = (InvocationTargetException) pae.getException(); throw ex.getTargetException(); } } else { try { ReflectionUtils.makeAccessible(initMethod); //經過反射調用初始化方法 initMethod.invoke(bean); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
由上代碼咱們知道爲何會出現上面執行順序的結果了吧!同時咱們還發現afterPropertiesSet方法不只先執行,也是直接調用bean的afterPropertiesSet方法進行調用,而init-method初始方法是經過反射方式調用的。測試
經過上面實現及代碼咱們能夠得出結果:1.spring爲咱們提供兩種初始化bean方法,實現InitializingBean接口和配置init-method。2.實現InitializingBean接口的方式由於是直接對bean調用afterPropertiesSet方法因此比init-method配置反射方式調用效率上面會高一點,可是也增長了跟spring框架的耦合度。debug