`
michael.softtech
  • 浏览: 206398 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

spring源码分析之——Spring bean的加载入口

阅读更多

同前一篇一样,本文的分析还是基于Spring的web应用。

 

从web.xml里面配置的ContextLoaderListener开始。

ContextLoaderListener引用了一个ContextLoader(可以是它自身);

ContextLoader引用了一个WebApplicationContext;

WebApplicationContext本身是一个beanFactory. 如果不指定,默认的实现类是

XmlWebApplicationContext--这个类的实例是一个beanFactory,同时也引用了一个BeanFactory. (Decorator Pattern);

 

其中bean的加载是由AbstractApplicationContext的refresh方法调用的。

为了稍微形象的描述,我把refresh方法的调用层次贴了出来。

在ContextLoader的createWebApplicationContext里面,新建了一个ApplicationContext,并且刷新这个context.

新建的代码:

ConfigurableWebApplicationContext wac =
				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

 刷新的代码:

 

wac.refresh();

 

refresh方法的实现是在XmlWebApplicationContext的父类AbstractApplicationContext里面实现的。

refresh里面完成了WebApplicationContext里面的beanfactory的初始化和bean载入,beanfactorypostprocessor的调用,beanpostprocessor的注册,ApplicationEvent的监听和注册,non-lazy-init的bean的初始化。

换言之,已经把该准备的都准备好了,只需要有请求来获取bean,就根据情况或返回已经初始化的bean或进行bean的Instantiation 和 Initialization。

源码如下:

 

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}
 

    注意其中的obtainFreshBeanFactory方法,beanFactory的初始化是由这个方法调用的。

 

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}
 

  继续追踪refreshBeanFactory方法,发现是在AbstractRefreshableApplicationContext中实现的。

 

@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
 

   由此可见,正是在refreshBeanFactory中,新建了一个DefaultListableBeanFactory并且载入了所有BeanDefinition.(载入过程在后续的篇章中继续分析)。

 

OK.现在脉络清楚了。我们知道了contextLoader在哪里获取了WebApplicationContext,知道了WebApplicationContext在哪里获取了beanFactory,知道了beanFactory在哪里创建和载入bean.

后面需要关注的就是bean的载入和初始话过程了。具体细节在后续的文章里面分析。

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics