spring容器:InitializingBean接口的使用

    首先我们来看一下InitializingBean接口,发现它只有一个方法,所以实现该接口只需实现这个方法就可以了。

package org.springframework.beans.factory;

public interface InitializingBean {

	void afterPropertiesSet() throws Exception;

}

    我们来定义一个service实现该接口,测试一下该接口提供的初始化功能,同时与init-method配置的初始化方法进行比较。

public class PlatformxService implements InitializingBean{

	
	@Override
	public void afterPropertiesSet() throws Exception {	
		System.out.println("初始化执行:afterPropertiesSet");
	}
	
	public void initMethod(){
		System.out.println("初始化执行:initMethod");
	}
}

    在配置文件中进行该service配置

<bean id="platformxService" class="com.sfpay.platformx.service.PlatformxService" init-method="initMethod" />

    因为我搭建的是web工程,这里启动容器观察初始化方法执行顺序

初始化执行: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配置初始化方法调用过程

	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框架的耦合度。

转载于:https://my.oschina.net/u/3100849/blog/848563

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值