一、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中类的职责分工相当的明确;
分享到:
相关推荐
这里提到的是一组完整的Spring库,包括`spring-core`、`spring-context`、`spring-webmvc`、`spring-web`、`spring-beans`、`spring-test`、`spring-jdbc`、`spring-orm`、`spring-aop`和`spring-tx`,它们都是3.2.0...
《Spring框架深度解析》 Spring Framework,作为Java开发领域中的基石,是企业级应用开发的首选框架。"spring-framework-master"这一压缩包包含了Spring框架的完整源码,为我们提供了深入理解这一强大工具的绝佳...
3. **spring-context-3.0.xsd**: Spring Context 是 Spring 框架的扩展,它提供了更丰富的上下文环境,包括国际化、事件广播、AOP 代理等功能。`spring-context-3.0.xsd` 文件包含了在上下文环境中配置的各种元素...
Spring提供了基于类型、名称等多种方式进行依赖解析。 综上所述,Spring中的Bean配置提供了丰富的选项来满足不同场景的需求,无论是简单的单例对象,还是复杂的依赖关系,都可以通过灵活的配置方式进行管理。通过...
它解析`<bean>`标签,从中提取出`class`属性(定义bean的实现类)、`parent`属性(定义父bean)、以及其他的属性,如`scope`(作用域)、`abstract`(是否为抽象bean)、`lazy-init`(是否延迟初始化)、`autowire`...
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=...
3. **Spring Context**:`spring-context-4.2.5.RELEASE.jar`扩展了Spring Core的功能,提供了一个应用上下文,它是bean的容器,可以管理和查找bean,并且支持消息处理、AOP(Aspect Oriented Programming,面向切面...
《跟我学Spring3-源码》教程是一份深入解析Spring框架3.x版本核心源码的教育资源,适合对Java和J2EE技术有一定基础的开发者学习。本教程旨在帮助读者理解Spring框架的工作原理,提高在实际项目中的应用能力。通过...
《Spring Framework 5.1.x 源码解析详细注解》 Spring Framework作为Java开发中的核心框架,其设计理念和实现机制对理解企业级应用的构建至关重要。本资源提供了Spring 5.1.x版本的源码详细注解,旨在帮助开发者...
《Spring Framework 5.1.4源码深度解析》 Spring Framework是Java开发中的核心框架,它为构建高质量的企业级应用提供了全面的支持。5.1.4版本是Spring的重要里程碑,引入了诸多新特性和改进,旨在提升性能、增强可...
### Spring Framework 4.3.19版本关键知识点解析 #### 一、Spring框架概览 **1. 开始使用Spring** - **Spring框架简介**:Spring是一个开源框架,最初由Rod Johnson创建,旨在简化企业级Java应用的开发。Spring...
《Spring Framework 1.0-m2深度解析》 Spring Framework,作为Java开发中不可或缺的开源框架,自其诞生以来就以其强大的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)特性赢得了广大开发者的心...
- **Bean容器**:是Spring的核心,负责管理对象的生命周期和依赖关系,通过XML或注解实现bean的配置。 - **AOP**:提供面向切面编程,允许开发者定义方法拦截器和切点,实现代码的解耦和模块化。 3. **模块详解**...
1. **Bean定义**:在Spring 3的DTD配置中,我们可以定义bean的实例,指定其类、构造函数参数、属性注入、初始化方法和销毁方法。例如,`<bean id="exampleBean" class="com.example.ExampleClass">`。 2. **依赖...
2. 快速导航:通过快捷键或菜单,可以快速跳转到Spring Bean定义的位置,便于查看和修改配置。 3. 智能提示:在编写XML配置文件时,插件会提供自动提示,减少错误和遗漏。 4. 依赖注入分析:分析项目中的Bean依赖...
《Spring Framework 5.2.3源码深度解析》 Spring Framework是Java开发中的核心框架,它为构建高质量的应用提供了全面的基础设施。5.2.3版本是Spring的一个稳定版本,包含了众多改进和新特性。这个官方原版源码包为...
《Spring Framework 4.3.0.RELEASE源码解析与深度探索》 Spring Framework作为Java领域最广泛应用的轻量级框架之一,其4.3.0.RELEASE版本的发布为开发者提供了更稳定、高效的服务。这个版本的成功编译,意味着我们...
9. **依赖注入**:Spring的核心特性之一,通过@Autowired注解自动装配bean的依赖。 10. **RESTful Web服务**:如何使用Spring MVC创建符合REST原则的服务,如HTTP动词(GET、POST、PUT、DELETE)的映射。 在压缩包...
本文将围绕Spring Framework 4.2.0.RELEASE这一版本,深入解析其特性、核心概念以及使用方法。 首先,4.2.0.RELEASE是Spring框架的一个稳定版本,它在4.x系列中引入了多项改进和新特性。这些改进旨在提升性能,增强...
《Spring框架5.2.25.RELEASE源码解析》 Spring Framework是Java开发领域中最受欢迎的开源框架之一,以其模块化、松耦合和强大的功能特性,深受开发者喜爱。5.2.25.RELEASE作为Spring框架的一个稳定版本,为开发者...