1.Spring中最核心的两个类

1)DefaultListableBeanFactory

  XmlBeanFactory继承自DefaultListableBeanFactory,DefaultListableBeanFactory是整个bean加载的核心部分,是Spring加载及注册bean的默认实现

2)XmlBeanDefinitionReader

2.示例代码

BeanFactory bf=new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));

XmlBeanFactory.class
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader; public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, (BeanFactory)null);
} public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader = new XmlBeanDefinitionReader(this);
this.reader.loadBeanDefinitions(resource);
}
}
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return this.loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource){
....  

  InputSource inputSource = new InputSource(inputStream);//通过SAX方式解析XML文件
....
  this.doLoadBeanDefinitions(inputSource, encodedResource.getResource()); }
 
 

3.配置文件的封装

Resource implements InputStreamResource

4.AbstractAutowireCapableBeanFactory.ignoreDependencyInterface()

忽略给定接口的自动装配功能

5.加载Bean

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
int validationMode = this.getValidationModeForResource(resource);//获取xml文件的验证模式
Document doc = this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware());//加载XML文件
return this.registerBeanDefinitions(doc, resource);//返回注册bean的信息
} catch (BeanDefinitionStoreException var5) {
throw var5;
} catch (SAXParseException var6) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
} catch (SAXException var7) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
} catch (ParserConfigurationException var8) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
} catch (IOException var9) {
throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
} catch (Throwable var10) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
}
}

1)获取xml文件的验证模式

getValidationModeForResource(resource);
protected int getValidationModeForResource(Resource resource) {
int validationModeToUse = this.getValidationMode();
if (validationModeToUse != 1) {
return validationModeToUse;
} else {
      //如果没有设定模式则进行自动检测模式
int detectedMode = this.detectValidationMode(resource);
return detectedMode != 1 ? detectedMode : 3;
}
}
protected int detectValidationMode(Resource resource) {
if (resource.isOpen()) {
throw new BeanDefinitionStoreException("Passed-in Resource [" + resource + "] contains an open stream: " + "cannot determine validation mode automatically. Either pass in a Resource " + "that is able to create fresh streams, or explicitly specify the validationMode " + "on your XmlBeanDefinitionReader instance.");
} else {
InputStream inputStream;
try {
inputStream = resource.getInputStream();
} catch (IOException var5) {
throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " + "Did you attempt to load directly from a SAX InputSource without specifying the " + "validationMode on your XmlBeanDefinitionReader instance?", var5);
} try {
          //将自动检测模式委托给了XmlValidationModeDetector类
           return this.validationModeDetector.detectValidationMode(inputStream);
       } catch (IOException var4) {
          throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: an error occurred whilst reading from the InputStream.", var4);
       }
     }
  }

2)加载XML文件,并得到对应的Document

委托给DocumentLoader类

EntityResolver的用法

EntityResolver的作用是项目本身就可以提供一个如何寻找DTD声明的方法,即由程序来实现寻找DTD声明的过程,比如我们将DTD文件放到项目中某处,在实现时直接将此文档读取并返回给SAX即可。这样就避免了通过网络来寻找相应的声明。

验证文件默认的加载方式是通过URL进行网络下载获取,这样会造成延迟,用户体验也不好,一般的做法都是将验证文件放在自己的工程里。

public interface EntityResolver {
public abstract InputSource resolveEntity (String publicId,
String systemId)
throws SAXException, IOException; }

3)返回注册bean的信息

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
      //单一职责原则
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
int countBefore = this.getRegistry().getBeanDefinitionCount();
      //加载及注册bean
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
this.doRegisterBeanDefinitions(root);
}
解析并注册BeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute("profile");
if (StringUtils.hasText(profileSpec)) {
Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
return;
}
} BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = this.createHelper(this.readerContext, root, parent);
this.preProcessXml(root);//模板方法模式
this.parseBeanDefinitions(root, this.delegate);
this.postProcessXml(root);
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
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;
if (delegate.isDefaultNamespace(ele)) {
this.parseDefaultElement(ele, delegate);//处理默认Bean声明
} else {
delegate.parseCustomElement(ele);//处理自定义Bean声明
}
}
}
} else {
delegate.parseCustomElement(root);
}
}

Spring源码学习笔记1的更多相关文章

  1. Spring源码学习笔记9——构造器注入及其循环依赖

    Spring源码学习笔记9--构造器注入及其循环依赖 一丶前言 前面我们分析了spring基于字段的和基于set方法注入的原理,但是没有分析第二常用的注入方式(构造器注入)(第一常用字段注入),并且在 ...

  2. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  3. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  4. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  5. spring源码学习笔记之容器的基本实现(一)

    前言 最近学习了<<Spring源码深度解析>>受益匪浅,本博客是对学习内容的一个总结.分享,方便日后自己复习或与一同学习的小伙伴一起探讨之用. 建议与源码配合使用,效果更嘉, ...

  6. Spring源码学习笔记之bean标签属性介绍及作用

    传统的Spring项目, xml 配置bean在代码中是经常遇到, 那么在配置bean的时候,这些属性的作用是什么呢? 虽然说现在boot项目兴起,基于xml配置的少了很多, 但是如果能够了解这些标签 ...

  7. Spring源码学习笔记之基于ClassPathXmlApplicationContext进行bean标签解析

    bean 标签在spring的配置文件中, 是非常重要的一个标签, 即便现在boot项目比较流行, 但是还是有必要理解bean标签的解析流程,有助于我们进行 基于注解配置, 也知道各个标签的作用,以及 ...

  8. Spring源码学习笔记2

    1.默认标签的解析 对四种不同标签的解析 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate dele ...

  9. spring源码学习之路---IOC初探(二)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章当中我没有提及具体的搭 ...

随机推荐

  1. 软件工程——四则运算py(我小学的时候怎么没用过这东西?)

    题目:实现一个自动生成小学四则运算题目的命令行程序 github地址:https://github.com/ILTHEW/wc.git 主编:黄晖朝3116005178 助手:朱健栋311600520 ...

  2. String字符串的常用方法

    1.substr():可在字符串中抽取从 start 下标开始的指定数目的字符. stringObject.substr(start,length) start:必需.要抽取的子串的起始下标.必须是数 ...

  3. angular 组件学习-组件内属性绑定

    #组件内的属性(元素的属性)绑定(property binding) 应用场景:通过改变DOM元素的属性,动态显示/隐藏一个元素 知识点:HTML 属性与DOM属性的区别 改变HTMl属性,浏览器需要 ...

  4. CSS3特性

    2018-08-20 CSS3:用于控制网页的样式和布局 1.transform:rotate(30deg);      CSS3 模块 选择器 盒模型 背景和边框 文字特效 2D/3D转换 动画 多 ...

  5. 深入理解Redis系列之SpringBoot集成Redis

    SpringBoot环境 快速搭建一个SpringBoot工程 进入 https://start.spring.io 网站, 使用该网站初始化一个SpringBoot工程 添加相关依赖 因为使用spr ...

  6. result type

    <result-types> <result-type name="chain" class="com.opensymphony.xwork2.Acti ...

  7. 电子签名在K2中的应用

    全球越来越多的企业开始使用电子签名(即eSignatures),在减少碳排放的同时简化业务流程,提高文档安全性,便于记录保存,并降低企业成本.在美国法律下,电子签名具备等同于手写签名的法律效力. 什么 ...

  8. C# [WIN32] [API] Global Hook

    NativeMethods.cs: using System; using System.Runtime.InteropServices; namespace GlobalHook { interna ...

  9. 北航OO第二单元总结

    电梯调度的设计策略 第一次作业是单部多线程傻瓜电梯 这次作业的电梯名副其实是一部傻瓜电梯,每次只能运一个人.出于线程安全的考虑,选择了阻塞队列.然后按照先来先服务的原则服务下一个指令.没有什么复杂的设 ...

  10. JQuery案例二:实现全选、全不选和反选

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...