Spring源码解析和配置文件加载
2015-08-19 17:21
681 查看
Spring类的继承结构图:
Spring运用了大量的模板方法模式和策略模式,所以各位看源码的时候,务必留意,每一个继承的层次都有不同的作用,然后将相同的地方抽取出来,依赖抽象将不同的处理按照不同的策略去处理。
步骤A. 读取 Resource 文件形成 Document 模型
类图: XmlBeanFactory -> XmlBeanDefinitionReader
Spring 使用 XmlBeanDefinitionReader 来读取并解析 xml 文件,XmlBeanDefinitionReader 是 BeanDefinitionReader 接口的实现。
BeanDefinitionReader 定义了 Spring 读取 Bean 定义的一个接口,这个接口中有一些 loadBeanDefinitions 方法, 用于读取 Bean 配置。
BeanDefinitionReader 接口有两个具体的实现,其中之一就是从 Xml 文件中读取配置的 XmlBeanDefinitionReader,另一个则是从 Java Properties 文件中读取配置的PropertiesBeanDefinitionReader。
(注:开发人员也可以提供自己的 BeanDefinitionReader 实现,根据自己的需要来读取 spring bean 定义的配置。)
步骤B. 解析 Document 得到 Bean 配置
类图: XmlBeanDefinitionReader-> BeanDefinitionDocumentReader
BeanDefinitionDocumentReader 接口中只定义了一个方法 registerBeanDefinitions. 有一个默认实现 DefaultBeanDefinitionDocumentReader.
DefaultBeanDefinitionDocumentReader 主要完成两件事情,解析 <bean> 元素,为扩展 spring 的元素寻找合适的解析器,并把相应的元素交给解析器解析。
过程:
在 XmlBeanFactory 中创建了 XmlBeanDefinitionReader 的实例,并在 XmlBeanFactory 的构造方法中调用了 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法,由 loadBeanDefinitions
方法负责加载 bean 配置并把 bean 配置注册到 XmlBeanFactory 中。
在 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法中, 调用 DefaultDocumentLoader 的 loadDocument 读取配置文件为 Document, 然后调用 BeanDefinitionDocumentReader
的 registerBeanDefinitions 方法 来解析 Bean.
源码解析:
在XmlBeanFactory初始化时, 需要指定Resource对象.
Java代码
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)
throws BeansException
{
super(parentBeanFactory);
reader = new XmlBeanDefinitionReader(this);
reader.loadBeanDefinitions(resource);
}
1. 先来分析下XmlBeanDefinitionReader这个类.
Java代码
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader
接着
Java代码
public abstract class AbstractBeanDefinitionReader
implements BeanDefinitionReader
再继续
Java代码
public interface BeanDefinitionReader
在BeanDefinitionReader中定义有许多loadBeanDefinitions方法
Java代码
public abstract int loadBeanDefinitions(Resource resource)
throws BeanDefinitionStoreException;
public abstract int loadBeanDefinitions(Resource aresource[])
throws BeanDefinitionStoreException;
public abstract int loadBeanDefinitions(String s)
throws BeanDefinitionStoreException;
public abstract int loadBeanDefinitions(String as[])
throws BeanDefinitionStoreException;
来回头看XmlBeanDefinitionReader对loadBeanDefinitions方法的实现
在loadBeanDefinitions方法中调用了doLoadBeanDefinitions方法, 跟踪doLoadBeanDefinitions方法
Java代码
Document doc = documentLoader.loadDocument(inputSource, getEntityResolver(), errorHandler, validationMode, isNamespaceAware());
通过一个叫documentLoader的东西的loadDocument方法来加载配置文件形成DOM, 来看看documentLoader
Java代码
private DocumentLoader documentLoader
...
documentLoader = new DefaultDocumentLoader();
跟踪到DefaultDocumentLoader
Java代码
public class DefaultDocumentLoader
implements DocumentLoader
...
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware)
throws Exception
{
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if(logger.isDebugEnabled())
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}
...
哦哦, 我们知道了, 是通过sax解析得到Dom的, 至于怎么解析, 不属于Spring范畴, 不做研究.
在这一步, 已完成了从配置文件读取到Domcument. 接着要开始解析Dom了
再继续, 解析成Dom后接着调用了registerBeanDefinitions方法
Java代码
return registerBeanDefinitions(doc, resource);
来看看registerBeanDefinitions的实现
Java代码
...
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
...
在这里, 有一个BeanDefinitionDocumentReader接口, 实际上Spring对它有一个默认的实现类叫DefaultBeanDefinitionDocumentReader, 来看看它的家族
Java代码
public class DefaultBeanDefinitionDocumentReader
Java代码
public interface BeanDefinitionDocumentReader
BeanDefinitionDocumentReader只有一个registerBeanDefinitions方法
Java代码
public abstract void registerBeanDefinitions(Document document, XmlReaderContext xmlreadercontext)
throws BeanDefinitionStoreException;
该方法需要两个参数, 一个是Document模型,这个应该是我们读取配置文件获取到的, 另一个是XmlReaderContext对象, 我们在上面方法中看到是通过createReaderContext(resource)得到的, 那就看看具体如何得到
Java代码
protected XmlReaderContext createReaderContext(Resource resource)
{
if(namespaceHandlerResolver == null)
namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
return new XmlReaderContext(resource, problemReporter, eventListener, sourceExtractor, this, namespaceHandlerResolver);
}
能过构造函数new出来的, 且有一个重要参数resource
再继续来看DefaultBeanDefinitionDocumentReader对BeanDefinitionDocumentReader的registerBeanDefinitions方法实现
Java代码
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
{
...
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
...
parseBeanDefinitions(root, delegate);
...
}
嘿嘿, 开始解析Dom了哦, 其中主要是parseBeanDefinitions方法, 来看看具体是如何解析的
Java代码
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
{
if(delegate.isDefaultNamespace(root.getNamespaceURI()))
{
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); i++)
{
org.w3c.dom.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);
}
}
看到了吧, 循环解析Domcument节点
parseDefaultElement方法和delegate的parseCustomElement方法
先来看parseDefaultElement方法
Java代码
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
{
if(DomUtils.nodeNameEquals(ele, "import"))
importBeanDefinitionResource(ele);
else
if(DomUtils.nodeNameEquals(ele, "alias"))
processAliasRegistration(ele);
else
if(DomUtils.nodeNameEquals(ele, "bean"))
processBeanDefinition(ele, delegate);
}
看到这就很清楚了, 就是根据节点的名称作不同解析, 如我们Spring配置文件中常有以下几种配置
Java代码
<import resource="classpath:xxx" />
<bean id="xxx" class="xxx.xxx.xxx" />
<alias name="xxxx" alias="yyyyy"/>
对<import>节点, 调用importBeanDefinitionResource方法解析, 此方法中, 又回到第一步读取配置文件并解析. 如此递归循环.
Java代码
...
Resource relativeResource = getReaderContext().getResource().createRelative(location);
int importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
...
对<alias>节点, 调用processAliasRegistration进行别名解析
我们主要看对<bean>节点调用processBeanDefinition进行解析
Java代码
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
{
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null)
{
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try
{
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch(BeanDefinitionStoreException ex)
{
getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
}
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
嘿嘿, 又用到delegate对象了, 且调用它的BeanDefinitionHolder方法, 返回一个BeanDefinitionHolder, 进去看它的parseBeanDefinitionElement方法
Java代码
public class BeanDefinitionParserDelegate
{
private final Set usedNames = new HashSet();
...
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)
{
... 解析id, name等属性, 并验证name是否唯一, 并将name保存在usedNames中
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
...
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
...
}
可以看到, 在BeanDefinitionHolder中保存了BeanDefinition的定义
OK, 重头戏开始, 最经典的部分出现了, 请看parseBeanDefinitionElement方法
Java代码
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean)
{
...
代码太长, 请参考具体代码
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(parent, className, readerContext.getBeanClassLoader());
...
return abstractbeandefinition;
...
}
在这个方法中, 解析了bean的所有属性, 有最常用的class, scope, lazy-init等等. 并返回一个AbstractBeanDefinition实例. 至于具体怎么解析, 就只能进一步跟踪了, 不过既然到了这一步, 已经明白了它的基本原理, 具体实现就不作介绍
这一步将节点解析成BeanDefinitionHolder对象, 再看看如何注册, 回到DefaultBeanDefinitionDocumentReader的processBeanDefinition方法
看到对解析到的bdHolder对象又做了decorateBeanDefinitionIfRequired操作, 来看看实现
... 暂留空
接着调用了BeanDefinitionReaderUtils的registerBeanDefinition方法注册bdHolder, 来看看如何实现的
Java代码
public class BeanDefinitionReaderUtils
{
public static void registerBeanDefinition(BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory)
throws BeanDefinitionStoreException
{
String beanName = bdHolder.getBeanName();
beanFactory.registerBeanDefinition(beanName, bdHolder.getBeanDefinition());
String aliases[] = bdHolder.getAliases();
if(aliases != null)
{
for(int i = 0; i < aliases.length; i++)
beanFactory.registerAlias(beanName, aliases[i]);
}
}
}
看吧, 又调用了BeanDefinitionRegistry的registerBeanDefinition方法, 跟踪之 (这个要看DefaultListableBeanFactory的实现)
Java代码
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry
{
private final Map beanDefinitionMap;
private final List beanDefinitionNames;
...
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException
{
...
Object oldBeanDefinition = beanDefinitionMap.get(beanName);
...
beanDefinitionMap.put(beanName, beanDefinition);
...
}
}
这里, 看到了一个最最重要的对象就是beanDefinitionMap, 这个map存放了所有的bean对象, 和我们通常讲的容器概念最为接近, getBean时实际是也是从这里辚取对象, 相同的还有一个beanDefinitionNames, 但这个只保存bean的名称
完成上面之后, 还有一步操作beanFactory.registerAlias(beanName, aliases[i]);
这个实现实际是上AbstractBeanFactory抽象类所定义的
Spring运用了大量的模板方法模式和策略模式,所以各位看源码的时候,务必留意,每一个继承的层次都有不同的作用,然后将相同的地方抽取出来,依赖抽象将不同的处理按照不同的策略去处理。
步骤A. 读取 Resource 文件形成 Document 模型
类图: XmlBeanFactory -> XmlBeanDefinitionReader
Spring 使用 XmlBeanDefinitionReader 来读取并解析 xml 文件,XmlBeanDefinitionReader 是 BeanDefinitionReader 接口的实现。
BeanDefinitionReader 定义了 Spring 读取 Bean 定义的一个接口,这个接口中有一些 loadBeanDefinitions 方法, 用于读取 Bean 配置。
BeanDefinitionReader 接口有两个具体的实现,其中之一就是从 Xml 文件中读取配置的 XmlBeanDefinitionReader,另一个则是从 Java Properties 文件中读取配置的PropertiesBeanDefinitionReader。
(注:开发人员也可以提供自己的 BeanDefinitionReader 实现,根据自己的需要来读取 spring bean 定义的配置。)
步骤B. 解析 Document 得到 Bean 配置
类图: XmlBeanDefinitionReader-> BeanDefinitionDocumentReader
BeanDefinitionDocumentReader 接口中只定义了一个方法 registerBeanDefinitions. 有一个默认实现 DefaultBeanDefinitionDocumentReader.
DefaultBeanDefinitionDocumentReader 主要完成两件事情,解析 <bean> 元素,为扩展 spring 的元素寻找合适的解析器,并把相应的元素交给解析器解析。
过程:
在 XmlBeanFactory 中创建了 XmlBeanDefinitionReader 的实例,并在 XmlBeanFactory 的构造方法中调用了 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法,由 loadBeanDefinitions
方法负责加载 bean 配置并把 bean 配置注册到 XmlBeanFactory 中。
在 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法中, 调用 DefaultDocumentLoader 的 loadDocument 读取配置文件为 Document, 然后调用 BeanDefinitionDocumentReader
的 registerBeanDefinitions 方法 来解析 Bean.
源码解析:
在XmlBeanFactory初始化时, 需要指定Resource对象.
Java代码
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)
throws BeansException
{
super(parentBeanFactory);
reader = new XmlBeanDefinitionReader(this);
reader.loadBeanDefinitions(resource);
}
1. 先来分析下XmlBeanDefinitionReader这个类.
Java代码
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader
接着
Java代码
public abstract class AbstractBeanDefinitionReader
implements BeanDefinitionReader
再继续
Java代码
public interface BeanDefinitionReader
在BeanDefinitionReader中定义有许多loadBeanDefinitions方法
Java代码
public abstract int loadBeanDefinitions(Resource resource)
throws BeanDefinitionStoreException;
public abstract int loadBeanDefinitions(Resource aresource[])
throws BeanDefinitionStoreException;
public abstract int loadBeanDefinitions(String s)
throws BeanDefinitionStoreException;
public abstract int loadBeanDefinitions(String as[])
throws BeanDefinitionStoreException;
来回头看XmlBeanDefinitionReader对loadBeanDefinitions方法的实现
在loadBeanDefinitions方法中调用了doLoadBeanDefinitions方法, 跟踪doLoadBeanDefinitions方法
Java代码
Document doc = documentLoader.loadDocument(inputSource, getEntityResolver(), errorHandler, validationMode, isNamespaceAware());
通过一个叫documentLoader的东西的loadDocument方法来加载配置文件形成DOM, 来看看documentLoader
Java代码
private DocumentLoader documentLoader
...
documentLoader = new DefaultDocumentLoader();
跟踪到DefaultDocumentLoader
Java代码
public class DefaultDocumentLoader
implements DocumentLoader
...
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware)
throws Exception
{
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if(logger.isDebugEnabled())
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}
...
哦哦, 我们知道了, 是通过sax解析得到Dom的, 至于怎么解析, 不属于Spring范畴, 不做研究.
在这一步, 已完成了从配置文件读取到Domcument. 接着要开始解析Dom了
再继续, 解析成Dom后接着调用了registerBeanDefinitions方法
Java代码
return registerBeanDefinitions(doc, resource);
来看看registerBeanDefinitions的实现
Java代码
...
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
...
在这里, 有一个BeanDefinitionDocumentReader接口, 实际上Spring对它有一个默认的实现类叫DefaultBeanDefinitionDocumentReader, 来看看它的家族
Java代码
public class DefaultBeanDefinitionDocumentReader
Java代码
public interface BeanDefinitionDocumentReader
BeanDefinitionDocumentReader只有一个registerBeanDefinitions方法
Java代码
public abstract void registerBeanDefinitions(Document document, XmlReaderContext xmlreadercontext)
throws BeanDefinitionStoreException;
该方法需要两个参数, 一个是Document模型,这个应该是我们读取配置文件获取到的, 另一个是XmlReaderContext对象, 我们在上面方法中看到是通过createReaderContext(resource)得到的, 那就看看具体如何得到
Java代码
protected XmlReaderContext createReaderContext(Resource resource)
{
if(namespaceHandlerResolver == null)
namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
return new XmlReaderContext(resource, problemReporter, eventListener, sourceExtractor, this, namespaceHandlerResolver);
}
能过构造函数new出来的, 且有一个重要参数resource
再继续来看DefaultBeanDefinitionDocumentReader对BeanDefinitionDocumentReader的registerBeanDefinitions方法实现
Java代码
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
{
...
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
...
parseBeanDefinitions(root, delegate);
...
}
嘿嘿, 开始解析Dom了哦, 其中主要是parseBeanDefinitions方法, 来看看具体是如何解析的
Java代码
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
{
if(delegate.isDefaultNamespace(root.getNamespaceURI()))
{
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); i++)
{
org.w3c.dom.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);
}
}
看到了吧, 循环解析Domcument节点
parseDefaultElement方法和delegate的parseCustomElement方法
先来看parseDefaultElement方法
Java代码
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
{
if(DomUtils.nodeNameEquals(ele, "import"))
importBeanDefinitionResource(ele);
else
if(DomUtils.nodeNameEquals(ele, "alias"))
processAliasRegistration(ele);
else
if(DomUtils.nodeNameEquals(ele, "bean"))
processBeanDefinition(ele, delegate);
}
看到这就很清楚了, 就是根据节点的名称作不同解析, 如我们Spring配置文件中常有以下几种配置
Java代码
<import resource="classpath:xxx" />
<bean id="xxx" class="xxx.xxx.xxx" />
<alias name="xxxx" alias="yyyyy"/>
对<import>节点, 调用importBeanDefinitionResource方法解析, 此方法中, 又回到第一步读取配置文件并解析. 如此递归循环.
Java代码
...
Resource relativeResource = getReaderContext().getResource().createRelative(location);
int importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
...
对<alias>节点, 调用processAliasRegistration进行别名解析
我们主要看对<bean>节点调用processBeanDefinition进行解析
Java代码
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
{
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null)
{
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try
{
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch(BeanDefinitionStoreException ex)
{
getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
}
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
嘿嘿, 又用到delegate对象了, 且调用它的BeanDefinitionHolder方法, 返回一个BeanDefinitionHolder, 进去看它的parseBeanDefinitionElement方法
Java代码
public class BeanDefinitionParserDelegate
{
private final Set usedNames = new HashSet();
...
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)
{
... 解析id, name等属性, 并验证name是否唯一, 并将name保存在usedNames中
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
...
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
...
}
可以看到, 在BeanDefinitionHolder中保存了BeanDefinition的定义
OK, 重头戏开始, 最经典的部分出现了, 请看parseBeanDefinitionElement方法
Java代码
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean)
{
...
代码太长, 请参考具体代码
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(parent, className, readerContext.getBeanClassLoader());
...
return abstractbeandefinition;
...
}
在这个方法中, 解析了bean的所有属性, 有最常用的class, scope, lazy-init等等. 并返回一个AbstractBeanDefinition实例. 至于具体怎么解析, 就只能进一步跟踪了, 不过既然到了这一步, 已经明白了它的基本原理, 具体实现就不作介绍
这一步将节点解析成BeanDefinitionHolder对象, 再看看如何注册, 回到DefaultBeanDefinitionDocumentReader的processBeanDefinition方法
看到对解析到的bdHolder对象又做了decorateBeanDefinitionIfRequired操作, 来看看实现
... 暂留空
接着调用了BeanDefinitionReaderUtils的registerBeanDefinition方法注册bdHolder, 来看看如何实现的
Java代码
public class BeanDefinitionReaderUtils
{
public static void registerBeanDefinition(BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory)
throws BeanDefinitionStoreException
{
String beanName = bdHolder.getBeanName();
beanFactory.registerBeanDefinition(beanName, bdHolder.getBeanDefinition());
String aliases[] = bdHolder.getAliases();
if(aliases != null)
{
for(int i = 0; i < aliases.length; i++)
beanFactory.registerAlias(beanName, aliases[i]);
}
}
}
看吧, 又调用了BeanDefinitionRegistry的registerBeanDefinition方法, 跟踪之 (这个要看DefaultListableBeanFactory的实现)
Java代码
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry
{
private final Map beanDefinitionMap;
private final List beanDefinitionNames;
...
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException
{
...
Object oldBeanDefinition = beanDefinitionMap.get(beanName);
...
beanDefinitionMap.put(beanName, beanDefinition);
...
}
}
这里, 看到了一个最最重要的对象就是beanDefinitionMap, 这个map存放了所有的bean对象, 和我们通常讲的容器概念最为接近, getBean时实际是也是从这里辚取对象, 相同的还有一个beanDefinitionNames, 但这个只保存bean的名称
完成上面之后, 还有一步操作beanFactory.registerAlias(beanName, aliases[i]);
这个实现实际是上AbstractBeanFactory抽象类所定义的
相关文章推荐
- 从源码安装Mysql/Percona 5.5
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- 浅析Ruby的源代码布局及其编程风格
- asp.net 抓取网页源码三种实现方法
- JS小游戏之仙剑翻牌源码详解
- JS小游戏之宇宙战机源码详解
- jQuery源码分析之jQuery中的循环技巧详解
- 本人自用的global.js库源码分享
- java中原码、反码与补码的问题分析
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao
- 读取spring配置文件的方法(spring读取资源文件)
- java实现简单美女拼图游戏
- java基本教程之线程休眠 java多线程教程
- JSP开发中在spring mvc项目中实现登录账号单浏览器登录
- PHP网页游戏学习之Xnova(ogame)源码解读(六)