首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

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

2012-09-22 
spring源码分析之——Spring bean的加载入口同前一篇一样,本文的分析还是基于Spring的web应用。?从web.xml里

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

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

?

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

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

ContextLoader引用了一个WebApplicationContext;

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

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

?

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

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

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

在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中实现的。

?

@Overrideprotected 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的载入和初始话过程了。具体细节在后续的文章里面分析。

?

?

?

?

?

热点排行