您的位置:首页 > 编程语言 > Java开发

Spring源码分析----IoC容器(一)

2013-03-17 22:02 519 查看
Ioc容器主要包括org.springframework.beans 、org.springframework.context这两个包。主要的两个基类就是BeanFactory和ApplicationContext。ApplicationContext扩展了BeanFactory的功能,支持功能更强大,一般我们优先使用。下面我们来说说IoC容器的源码:

 

BeanFactory工厂类继承图:

 



 

说明:从上图可以看出BeanFactory主要有3个子接口:ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory,

他实现了所有的接口。那为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个 Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义Bean 的自动装配规则。这四个接口共同定义了Bean
的集合、Bean 之间的关系、以及 Bean 行为。

他们最终的实现类都是XmlBeanFactory类。也就是说Ioc容器最底层的实现是XmlBeanFactory。下面我们就从XmlBeanFactory来看一下基本的IoC容器的实现过程:

 

@Deprecated
public class XmlBeanFactory extends DefaultListableBeanFactory {

private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

/**
* Create a new XmlBeanFactory with the given resource,
* which must be parsable using DOM.
* @param resource XML resource to load bean definitions from
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}

/**
* Create a new XmlBeanFactory with the given input stream,
* which must be parsable using DOM.
* @param resource XML resource to load bean definitions from
* @param parentBeanFactory parent bean factory
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

XmlBeanFactory类源码中对类的定义:reads bean definitions from an XML document. Delegates to{@link XmlBeanDefinitionReader} underneath; effectively equivalent to using an XmlBeanDefinitionReader with a DefaultListableBeanFactory. 可以简单理解为XmlBeanFactory是一个可以读取xml文件方式定义的beanDefinition的IoC容器。

从上面源码中可以看出类中包含了一个XmlBeanDefinitionReader对象reader,根据reader对象去加载beanDefinition,也就是说对xml信息的处理实际上是由XmlBeanDefinitionReader类来操作的,this.reader.loadBeanDefinitions(resource)有一个参数resource,Resource类是spring为我们处理外部资源(URL资源、File资源资源、ClassPath相关资源等)提供的一个统一接口访问,里面包括了对资源的打开、读取、关闭等操作。也就是说reader对象把resource中的xml资源信息加载到beandefinition中。

说说beandefinition:简单理解就是一个javabean对象类,用来保存类如xml文件配置中的一个个bean信息。

 

因实际使用中我们使用ApplicationContext较多,下面我们主要分析下ApplicationContext容器:

看下ApplicationContext类结构图:



从上图中可以看出 ApplicationContext 继承了 BeanFactory,这也说明了 Spring 容器中运行的主体对象是 Bean,另外 ApplicationContext 继承了 ResourceLoader 接口,使得 ApplicationContext 可以访问到任何外部资源。

ApplicationContext 的子类主要包含两个方面:

ConfigurableApplicationContext 表示该 Context 是可修改的,也就是在构建 Context 中用户可以动态添加或修改已有的配置信息,它下面又有多个子类,其中最经常使用的是可更新的 Context,即 AbstractRefreshableApplicationContext 类。
WebApplicationContext 顾名思义,就是为 web 准备的 Context 他可以直接访问到 ServletContext,通常情况下,这个接口使用的少。

再往下分就是按照构建 Context 的文件类型,接着就是访问 Context 的方式。这样一级一级构成了完整的 Context 等级层次。

总体来说 ApplicationContext 必须要完成以下几件事:

标识一个应用环境

利用 BeanFactory 创建 Bean 对象
保存对象关系表
能够捕获各种事件
Context 作为 Spring 的 Ioc 容器,基本上整合了 Spring 的大部分功能,或者说是大部分功能的基础。

AbstractApplicationContext的refresh方法作为IoC运行的主要入口操作方法:

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;
}
}
}

bean装载时序图:



 

XmlBeanDefinitionReader类中操作流向:loadBeanDefinition()---->doLoadBeanDefinitions()---->registerBeanDefinitions(doc, resource) 转到-------》

DefaultBeanDefinitionDocumentReader:doRegisterBeanDefinitions(Element root)----》parseBeanDefinitions()

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}


 从上面看 这段就是对xml进行解析的过程,进入parseDefaultElement方法看看,

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}

这段对import、alias、普通bean分别做了处理,我们主要看普通bean的processBeanDefinition,

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}

BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); 这边把bean加工好了放到了beandefinition中,下面就是把bean信息存放到map中。

registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());这里把xml配置文件中的一个个bean 以beanName为key beanDefinition对象为值的方式存到DefaultListableBeanFactory类的beanDefinitionMap中。到此bean的装载过程就结束了。下一篇我们看看bean实例化的过程。

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: