首先咱们来看一下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