spring容器:InitializingBean接口的使用

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

相关文章
相关标签/搜索