一、Bean的解析(以XmlBeanFactory为例来说明)
1、构造级联容器
AbstractBeanFactory.java
public void setParentBeanFactory(BeanFactory parentBeanFactory) {
// 如果当前容器已经指定了父容器,且新的父容器与当前的父容器不相同,则出错了;
if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
}
this.parentBeanFactory = parentBeanFactory;
}
2、生成XmlBeanDefinitionReader
XmlBeanFactory.java
// new一个XmlBeanDefinitionReader,在解析bean配置文件时,直接将bean定义信息放到BeanDefinitionRegistry里
// 这里把当前容器作为参数传入,是因为XmlBeanFactory实现了BeanDefinitionRegistry接口
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
3、利用上面构造的reader解析XML文件,装载bean
this.reader.loadBeanDefinitions(resource);
解析
XmlBeanDefinitionReader.java
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);
}
// 这里使用ThreadLocal防止循环装载bean
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected recursive loading of " + encodedResource + " - check your import definitions!");
}
try {
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 {
// 装载完后,移除该bean定义文件
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.set(null);
}
}
}
XmlBeanDefinitionReader.java
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
// 对XML进行校验后,注册bean信息
return registerBeanDefinitions(doc, resource);
}
...
}
XmlBeanDefinitionReader.java
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
...
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 交由DefaultBeanDefinitionDocumentReader完成读取bean的工作
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回当前resource注册到容器中的bean的数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
DefaultBeanDefinitionDocumentReader.java
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
preProcessXml(root);
// 由代理类BeanDefinitionParserDelegate完成解析
parseBeanDefinitions(root, delegate);
postProcessXml(root);
}
DefaultBeanDefinitionDocumentReader.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++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
String namespaceUri = ele.getNamespaceURI();
if (delegate.isDefaultNamespace(namespaceUri)) {
// 解析每个element
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
DefaultBeanDefinitionDocumentReader.java
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);
}
}
从这里可以看到:
- 如果bean配置文件中使用到了import元素,也是在这里处理的,其处理过程和上面的一致;
- 如果是别名,则直接将别名注册到beanName上;
生成BeanDefinition
DefaultBeanDefinitionDocumentReader.java
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析element的亚属性,封装成BeanDefinition,然后和beanName、别名(主属性)一起组装成BeanDefinitionHolder
// 这里把解析bean元素的工作完成委托给BeanDefinitionParseDelegate类来完成
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 注册刚才生成的BeanDefinitionHolder到容器中
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));
}
}
注册到容器中
BeanDefinitionReaderUtils.java
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 注册bean信息
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (int i = 0; i < aliases.length; i++) {
registry.registerAlias(beanName, aliases[i]);
}
}
}
4、小结
- 其实,这里看着这么多代码,但其作用只有一个,那就是解析XML里的每个元素,获取Spring规范定义的bean的属性值,然后生成BeanDefinition实例;
- 上面提到一点,解析bean的繁锁工作全部由BeanDefinitionParseDelegate类来完成,从这一点也可以看出,Spring中类的职责分工相当的明确;
分享到:
相关推荐
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context=...
本次为spring解析配置文件中spring.xml的过程,并且根据解析的spring.xml中的<bean>节点加载bean到map中。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/jsps/"></property> <property name="suffix" value=".jsp"></property> </bean> ...
springBean加载过程源码解析文档,附有代码类名和行数
Data-JPA快速使用---我瞎写了》从核心实现和企业应用两个方面,由浅入深、由易到难地对Spring源码展开了系统的讲解,包括Spring的设计理念和整体架构、容器的基本实现、默认标签的解析、自定义标签的解析、bean的...
使用了dom4j相关包,spring通过反射机制实现bean的创建等,完成bean的管理
深度解析 Spring 源码探寻Bean的生命周期
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> <!-...
spring基础 Spring概述 Spring的简史 xml配置 注解配置 java配置 Spring概述 Spring的模块 核心容器CoreContainer Spring-Core Spring-Beans Spring-Context ...
2、spring-mvc配置文件包括两部分,一个是spring传统配置文件,在代码中为“applicationContext.xml”,主要配置代码中各种bean以及依赖关系;另外一个是spring-mvc特有的配置文件,处理跳转的代理类得(相当于...
Spring5.0源码深度解析之SpringBean循环依赖问题解决方案.docx
本篇文章主要介绍了Spring多种加载Bean方式解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
通过dom4j解析配置文件,得到list集合(存放Bean标签的id和class属性) * 3.通过反射实例化得到对应的实例化对象,放置在map中(map是键值对,可根据id获取值)(遍历list获取对应的class属性,利用class。formName...
2.5 关于切入点表达式解析 2.5.1 bean标签写法 2.5.2 within表达式 2.5.3 execution表达式 2.6 按照自定义注解进行拦截 2.6.1 自定义注解 2.6.2 切入点表达式写法 2.6.3 在service层实现类UserServiceImpl的addUser...
2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的...
Spring技术内幕:深入解析Spring架构与设计原理(第2部分) 《Spring技术内幕:深入解析Spring架构与设计原理》是Spring领域的问鼎之作,由业界拥有10余年开发经验的资深Java专家亲自执笔!Java开发者社区和Spring...
下载频道>资源分类>开发技术>Java>Spring技术内幕:深入解析Spring架构与设计原理 1/2 Spring技术内幕:深入解析Spring架构与设计原理 1/2资源大小:59MB 上传日期:2011-11-15 资源积分:5分 下载次数:30 上 传 者...
<bean class="org.springframework.web.servlet.mvc.annotation. AnnotationMethodHandlerAdapter"/> <!-- ③:对模型视图名称的解析,即在模型视图名称添加前后缀 --> <bean class="org.springframework.web....
//对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); ...
主要介绍了Spring动态加载bean后调用实现方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下