Spring源代码分析 -- IOC容器(一)

Spring是知道很久了,一直断断续续在看,不过用到它的机会不是很多,于是想阅读一下Spring的源代码来更深入的了解下这个框架(源代码的版本是2.5.6)。首先,当然是从Spring的IOC容器开始了,最基本的IOC容器就是org.springframework.beans.factory.BeanFactory了,这个接口定义了一个基本的IOC容器应该具有的行为,其源代码如下所示:

public interface BeanFactory {

/** 通过在bean的名字前加上&可以返回生成Bean的FactoryBean本身 */
String FACTORY_BEAN_PREFIX = "&";

/** 根据名字返回Bean */
Object getBean(String name) throws BeansException;

/** 根据名字和类型返回Bean */
Object getBean(String name, Class requiredType) throws BeansException;

/** 用于使用静态方法工厂创建prototype的bean,args是给工厂方法的参数 */
Object getBean(String name, Object[] args) throws BeansException;

/** 查询IOC容器中是否有特定名字的Bean */
boolean containsBean(String name);

/** 判断Bean是不是单例的 */
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

/** 判断Bean是不是原型的 */
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

/** 判断名字为name的Bean的类型是否是targetType */
boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;

/** 返回Bean的类型 */
Class getType(String name) throws NoSuchBeanDefinitionException;

/** 判断Bean的所有别名,如果使用别名查询的,那么Bean的原始名字也会返回的 */
String[] getAliases(String name);

}


BeanFactory是一切IOC容器类的基接口,它定义了IOC容器的基本行为,下面来看几个具体的实现类,首先从XmlBeanFactory开始。

public class XmlBeanFactory extends DefaultListableBeanFactory {

private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}

public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

}


这个类的构造函数说明了配置文件的载入过程,就是通过XmlBeanDefinitionReader的#loadBeanDefinitions()方法来载入的,源代码如下:

	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}


它又进一步调用了#loadBeanDefinitions(EncodedResource)这个方法,它的源代码如下。

	public int loadBeanDefinitions(EncodedResource encodedResource)
throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}

Set currentResources = (Set) this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
// 如果Set中已经包含了这个资源,那么就不要重复载入
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException("Detected recursive loading of "
+ encodedResource + " - check your import definitions!");
}
try {
// 构建一个解析XML使用的InputStream对象
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 实做Bean定义的载入
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
inputStream.close();
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException("IOException parsing XML document from "
+ encodedResource.getResource(), ex);
} finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.set(null);
}
}
}


这样,经过了一些列的处理,最后来到了实做载入的#doLoadBeanDefinitions()方法。

	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);

// 通过InputSource来载入XML到一个Document对象
Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(),
this.errorHandler, validationMode, isNamespaceAware());
// 注册Bean的定义
return registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line "
+ ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
} catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
} catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
} catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}


下面首先来看一下这个Document的获取过程,这里documentLoader是一个org.springframework.beans.factory.xml.DefaultDocumentLoader类的对象,通过它的#loadDocument()方法可以获得一个Document对象,这个过程先不去仔细看,主要来看一下这个#registerBeanDefinitions()方法。

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 支持老的XmlBeanDefinitionParser
if (this.parserClass != null) {
XmlBeanDefinitionParser parser = (XmlBeanDefinitionParser) BeanUtils
.instantiateClass(this.parserClass);
return parser.registerBeanDefinitions(this, doc, resource);
}
// 使用BeanDefinitionDocumentReader来载入
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 已经注册的Bean数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 注册Bean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}


这里XmlBeanDefinitionParser的处理就不仔细看了,因为是Spring为了兼容老的实现而保留的,下边主要来看一下使用BeanDefinitionDocumentReader的处理过程。

首先就应该是BeanDefinitionDocumentReader的构造,就是#createBeanDefinitionDocumentReader()方法

	protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return (BeanDefinitionDocumentReader) BeanUtils.instantiateClass(this.documentReaderClass);
}


这里的documentReaderClass这个变量的值为DefaultBeanDefinitionDocumentReader.class,也就是org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader,也就是BeanDefinitionDocumentReader的实现类。

下面来看看它的#registerBeanDefinitions()方法。

	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;

logger.debug("Loading bean definitions");
// 根元素
Element root = doc.getDocumentElement();

// 这个类很重要,主要是委托给它来实现解析
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);

// 如果想自己实现Bean的注册过程,可以继承DefaultBeanDefinitionDocumentReader,
// 然后覆盖#preProcessXml()和#postProcessXml()来完成更多的个性化实现。

// 处理XML前,默认无行为
preProcessXml(root);

// 解析Bean的定义
parseBeanDefinitions(root, delegate);

// 处理XML后,默认无行为
postProcessXml(root);
}


这个方法有两个部分需要考虑下,一个是BeanDefinitionParserDelegate实例的构建,另外一个是#parseBeanDefinitions()方法。

首先来看一下BeanDefinitionParserDelegate的构建

	protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root);
return delegate;
}


这里调用了BeanDefinitionParserDelegate的#initDefaults()方法来初始化,并把document的root元素作为参数传递了进去。这个方法主要是对一些全局属性的初始化,可以看看它的源代码:

	public void initDefaults(Element root) {
DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition();
// default-lazy-init -> 默认的延迟加载
defaults.setLazyInit(root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE));
// default-merge -> 对集合类的默认merge处理
defaults.setMerge(root.getAttribute(DEFAULT_MERGE_ATTRIBUTE));
// default-autowire -> 默认的自动装配
defaults.setAutowire(root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE));
// default-dependency-check -> 默认的依赖检测
defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
// default-autowire-candidates -> 查找自动装配的Bean的样式
if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
}
// default-init-method -> 默认初始化方法
if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
}
// default-destroy-method -> 模式销毁方法
if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
}
defaults.setSource(this.readerContext.extractSource(root));

this.defaults = defaults;
this.readerContext.fireDefaultsRegistered(defaults);
}


这个方法提供了针对根标签<beans>的属性(xml定义的bean的一些默认行为)的载入。在这里会看到很多spring配置文件中出现过的身影。

看过了BeanDefinitionParserDelegate之后,下面就来看看#parseBeanDefinitions()方法的定义吧:

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
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;
String namespaceUri = ele.getNamespaceURI();
if (delegate.isDefaultNamespace(namespaceUri)) {
// 解析默认的标签
parseDefaultElement(ele, delegate);
} else {
// 解析不是在默认命名空间的
delegate.parseCustomElement(ele);
}
}
}
} else {
// 解析不是在默认命名空间的
delegate.parseCustomElement(root);
}
}


下面是#parseDefaultElement()的定义:

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// <import>的处理
if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// <alias>的处理
else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// <bean>的处理
else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
}


#parseDefaultElement()包含了<beans>标签的所有子标签的处理。

剩下的内容下次再说。:)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值