Spring是知道很久了,一直断断续续在看,不过用到它的机会不是很多,于是想阅读一下Spring的源代码来更深入的了解下这个框架(源代码的版本是2.5.6)。首先,当然是从Spring的IOC容器开始了,最基本的IOC容器就是org.springframework.beans.factory.BeanFactory了,这个接口定义了一个基本的IOC容器应该具有的行为,其源代码如下所示:
BeanFactory是一切IOC容器类的基接口,它定义了IOC容器的基本行为,下面来看几个具体的实现类,首先从XmlBeanFactory开始。
这个类的构造函数说明了配置文件的载入过程,就是通过XmlBeanDefinitionReader的#loadBeanDefinitions()方法来载入的,源代码如下:
它又进一步调用了#loadBeanDefinitions(EncodedResource)这个方法,它的源代码如下。
这样,经过了一些列的处理,最后来到了实做载入的#doLoadBeanDefinitions()方法。
下面首先来看一下这个Document的获取过程,这里documentLoader是一个org.springframework.beans.factory.xml.DefaultDocumentLoader类的对象,通过它的#loadDocument()方法可以获得一个Document对象,这个过程先不去仔细看,主要来看一下这个#registerBeanDefinitions()方法。
这里XmlBeanDefinitionParser的处理就不仔细看了,因为是Spring为了兼容老的实现而保留的,下边主要来看一下使用BeanDefinitionDocumentReader的处理过程。
首先就应该是BeanDefinitionDocumentReader的构造,就是#createBeanDefinitionDocumentReader()方法
这里的documentReaderClass这个变量的值为DefaultBeanDefinitionDocumentReader.class,也就是org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader,也就是BeanDefinitionDocumentReader的实现类。
下面来看看它的#registerBeanDefinitions()方法。
这个方法有两个部分需要考虑下,一个是BeanDefinitionParserDelegate实例的构建,另外一个是#parseBeanDefinitions()方法。
首先来看一下BeanDefinitionParserDelegate的构建
这里调用了BeanDefinitionParserDelegate的#initDefaults()方法来初始化,并把document的root元素作为参数传递了进去。这个方法主要是对一些全局属性的初始化,可以看看它的源代码:
这个方法提供了针对根标签<beans>的属性(xml定义的bean的一些默认行为)的载入。在这里会看到很多spring配置文件中出现过的身影。
看过了BeanDefinitionParserDelegate之后,下面就来看看#parseBeanDefinitions()方法的定义吧:
下面是#parseDefaultElement()的定义:
#parseDefaultElement()包含了<beans>标签的所有子标签的处理。
剩下的内容下次再说。:)
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>标签的所有子标签的处理。
剩下的内容下次再说。:)