spring框架bean初始化之InitializingBean接口

本文探讨了在Spring框架中如何实现bean的自定义初始化,主要介绍了通过实现InitializingBean接口进行初始化的方法。文章详细讲解了InitializingBean接口的afterPropertiesSet方法,并通过示例展示了bean实例化后自动调用此方法的流程。同时,解析了Spring框架内部的doCreateBean和initializeBean方法,以及如何在这些方法中调用自定义的初始化方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

众所周知Spring框架主要的一个功能是IOC容器,IOC就是控制反转将本来需要我们手动实例化bean的过程,交给了Spring去完成。让Spring帮我们去实例化和维护bean。如果我们要在bean实例完成后需要执行自定义初始化方法怎么办呢?在Spring框架中提供了两种方式一种是在XML配置bean时指定init-method,另外一种方式是bean实现InitializingBean接口。接下来我们就看看Spring是怎么通过InitializingBean帮我们完成bean的自定初始化过程。

首先看下InitializingBean接口的定义,接口中包含afterPropertiesSet方法。

public interface InitializingBean {

	void afterPropertiesSet() throws Exception;

}

我们自定义一个接口HelloService,这个接口继承InitializingBean接口,定义如下:

public interface HelloService extends InitializingBean {
	
	int sayHello();

}

编写一个HelloService的实现类:

@Service
public class HelloServiceImpl implements HelloService{
	
	private Logger logger = LoggerFactory.getLogger(getClass());

	public String serviceName;
	@Override
	public int sayHello() {
		System.out.println(serviceName);
		return 1;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		logger.info("helloservice 执行初始化");
		this.serviceName = "helloSevice";
		
	}

}

启动tomcat容器,查看打印日志,可以看到HelloServiceImpl在创建实例后自动调用了afterPropertiesSet方法,完成了自定义的初始化流程。 

在Spring框架中这个执行过程是什么样的呢,Spring创建bean实例时需要执行doCreateBean方法,在创建完实例后会调用initializeBean方法执行初始过程。下面是doCreateBean的实现。

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
		mbd.resolvedTargetType = beanType;

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
                              //执行bean实例的初始化
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

在initializeBean的方法中调用了invokeInitMethods方法,在invokeInitMethods会判断bean是否实现了InitializingBean接口,如果实现了个该接口,则调用afterPropertiesSet方法执行自定义的初始化过程,invokeInitMethods实现代码如下:

	protected void invokeInitMethods(String beanName, final Object bean, 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(new PrivilegedExceptionAction<Object>() {
						@Override
						public Object run() throws Exception {
							((InitializingBean) bean).afterPropertiesSet();
							return null;
						}
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
                                 //调用afterPropertiesSet方法执行自定义初始化流程
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null) {
			String initMethodName = mbd.getInitMethodName();
			if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

在SpringMVC中AbstractHandlerMethodMapping就实现了InitializingBean接口,当一个RequestMappingHandlerMapping的实例创建完成后会接着调用afterPropertiesSet方法,扫描所有的controller完成所有的handler method的注册。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值