第六步:

  1. public abstract class AbstractApplicationContext extends DefaultResourceLoader
  2. implements ConfigurableApplicationContext, DisposableBean {
  3. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  4. refreshBeanFactory();//具体实现调用子类容器的refreshBeanFactory()方法
  5. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  6. if (logger.isDebugEnabled()) {
  7. logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
  8. }
  9. return beanFactory;
  10. }
  11.  
  12. ...
  13.  
  14. protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
  15. }

第七步:

  1. public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
  2.  
  3. /** Bean factory for this context */
  4. private DefaultListableBeanFactory beanFactory;
  5.  
  6. protected final void refreshBeanFactory() throws BeansException {
  7. //如果已经有beanfactory了,则销毁所有的bean,关闭beanfactory
  8. if (hasBeanFactory()) {
  9. destroyBeans();
  10. closeBeanFactory();
  11. }
  12. try {
  13. //得到一个默认的DefaultListableBeanFactory
  14. DefaultListableBeanFactory beanFactory = createBeanFactory();
  15. beanFactory.setSerializationId(getId());
  16. //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等
  17. customizeBeanFactory(beanFactory);
  18. //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
  19. loadBeanDefinitions(beanFactory);
  20. synchronized (this.beanFactoryMonitor) {
  21. this.beanFactory = beanFactory;
  22. }
  23. }
  24. catch (IOException ex) {
  25. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
  26. }
  27. }
  28.  
  29. //创建beanfactory
  30. protected DefaultListableBeanFactory createBeanFactory() {
  31. return new DefaultListableBeanFactory(getInternalParentBeanFactory());
  32. }
  33.  
  34. ...
  35. protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
  36. throws BeansException, IOException;
  37.  
  38. }

第八步:

  1. public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
  2.  
  3. /** Default config location for the root context */
  4. public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
  5.  
  6. /** Default prefix for building a config location for a namespace */
  7. public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
  8.  
  9. /** Default suffix for building a config location for a namespace */
  10. public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
  11.  
  12. @Override
  13. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
  14. // Create a new XmlBeanDefinitionReader for the given BeanFactory.
  15. //创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
  16. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
  17.  
  18. // Configure the bean definition reader with this context's
  19. // resource loading environment.
  20. //设置环境
  21. beanDefinitionReader.setEnvironment(this.getEnvironment());
  22. //为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的祖先父类AbstractApplicationContext,他继承DefaultResourceLoader,因此容器本身也是一个资源加载器
  23. beanDefinitionReader.setResourceLoader(this);
  24. //为Bean读取器设置SAX xml解析器
  25. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
  26.  
  27. // Allow a subclass to provide custom initialization of the reader,
  28. // then proceed with actually loading the bean definitions.
  29. //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
  30. initBeanDefinitionReader(beanDefinitionReader);
  31. //Bean读取器真正实现加载的方法
  32. loadBeanDefinitions(beanDefinitionReader);
  33. }
  34.  
  35. ...
  36.  
  37. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
  38. //获取配置资源的定位
  39. String[] configLocations = getConfigLocations();
  40. if (configLocations != null) {
  41. for (String configLocation : configLocations) {
  42. //XmlBean读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源
  43. reader.loadBeanDefinitions(configLocation);
  44. }
  45. }
  46. }
  47.  
  48. }

第九步:

  1. public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {
  2.  
  3. //从指定的资源加载bean定义,返回bean定义的数量
  4. public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
  5. ResourceLoader resourceLoader = getResourceLoader();//得到资源加载器
  6. if (resourceLoader == null) {
  7. throw new BeanDefinitionStoreException(
  8. "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
  9. }
  10.  
  11. if (resourceLoader instanceof ResourcePatternResolver) {
  12. // Resource pattern matching available.
  13. try {
  14. Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
  15. int loadCount = loadBeanDefinitions(resources);//得到加载bean定义的数量,而且在这里将bean定义注入进了spring容器中
  16. if (actualResources != null) {
  17. for (Resource resource : resources) {
  18. actualResources.add(resource);
  19. }
  20. }
  21. if (logger.isDebugEnabled()) {
  22. logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
  23. }
  24. return loadCount;
  25. }
  26. catch (IOException ex) {
  27. throw new BeanDefinitionStoreException(
  28. "Could not resolve bean definition resource pattern [" + location + "]", ex);
  29. }
  30. }
  31. else {
  32. // Can only load single resources by absolute URL.
  33. Resource resource = resourceLoader.getResource(location);
  34. int loadCount = loadBeanDefinitions(resource);
  35. if (actualResources != null) {
  36. actualResources.add(resource);
  37. }
  38. if (logger.isDebugEnabled()) {
  39. logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
  40. }
  41. return loadCount;
  42. }
  43. }
  44.  
  45. public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
  46. Assert.notNull(resources, "Resource array must not be null");
  47. int counter = 0;
  48. for (Resource resource : resources) {
  49. counter += loadBeanDefinitions(resource);//加载不同的资源类型,使用不同的具体子类来加载,这里使用的是xml。所以他的子类是XmlBeanDefinitionReader,还有一个子类是PropertiesBeanDefinitionReader
  50. }
  51. return counter;
  52. }
  53.  
  54. }

spring容器启动的加载过程(二)的更多相关文章

  1. spring容器启动的加载过程(三)

    第十步: public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { /** * Load bean def ...

  2. spring容器启动的加载过程(一)

    使用spring,我们在web.xml都会配置ContextLoaderListener <listener> <listener-class> org.springframe ...

  3. 微服务架构 | *2.3 Spring Cloud 启动及加载配置文件源码分析(以 Nacos 为例)

    目录 前言 1. Spring Cloud 什么时候加载配置文件 2. 准备 Environment 配置环境 2.1 配置 Environment 环境 SpringApplication.prep ...

  4. 1. spring5源码 -- Spring整体脉络 IOC加载过程 Bean的生命周期

    可以学习到什么? 0. spring整体脉络 1. 描述BeanFactory 2. BeanFactory和ApplicationContext的区别 3. 简述SpringIoC的加载过程 4. ...

  5. Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析

    Tomcat启动加载过程(一)的源码解析 今天,我将分享用源码的方式讲解Tomcat启动的加载过程,关于Tomcat的架构请参阅<Tomcat源码分析二:先看看Tomcat的整体架构>一文 ...

  6. jvm(1)类的加载(二)(自定义类加载器)

    [深入Java虚拟机]之四:类加载机制 1,从Java虚拟机的角度,只存在两种不同的类加载器: 1,启动类加载器:它使用C++实现(这里仅限于Hotspot,也就是JDK1.5之后默认的虚拟机,有其他 ...

  7. 深入理解 spring 容器,源码分析加载过程

    Spring框架提供了构建Web应用程序的全功能MVC模块,叫Spring MVC,通过Spring Core+Spring MVC即可搭建一套稳定的Java Web项目.本文通过Spring MVC ...

  8. spring启动component-scan类扫描加载过程(转)

    文章转自 http://www.it165.net/pro/html/201406/15205.html 有朋友最近问到了 spring 加载类的过程,尤其是基于 annotation 注解的加载过程 ...

  9. 【Spring源码分析系列】启动component-scan类扫描加载过程

    原文地址:http://blog.csdn.net/xieyuooo/article/details/9089441/ 在spring 3.0以上大家都一般会配置一个Servelet,如下所示: &l ...

随机推荐

  1. CentOS7 下安装telnet服务

    今天搞了下 Centos 7 下面升级 openssl 和 openssh ,顺便装了下 telnet # 安装 telnet 避免 ssh 无法登录 yum -y install xinetd te ...

  2. php学习笔记——表单

    13.表单 1)GET vs. POST GET 和 POST 都创建数组(例如,array( key => value, key2 => value2, key3 => value ...

  3. HTTPS详解

    HTTPS(Hypertext Transfer Protocol over Secure Socket Layer,基于SSL的HTTP协议)使用了HTTP协议,但HTTPS使用不同于HTTP协议的 ...

  4. mysql 创建用户与授权、修改密码

    mysql版本:5.6.35 1.创建用户 #foo表示你要建立的用户名,后面的123表示密码, #localhost限制在固定地址localhost登陆 CREATE USER foo@localh ...

  5. pro asp.net mvc5

    mvc 架构的每一个部分都是定义良好和自包含的,称为关注分离.域模型和控制器逻辑与UI是松耦合的.模型中操作数据的逻辑仅包含在模型中,显示数据的逻辑仅包含在视图中,而处理用户请求和用户输入的代码仅包含 ...

  6. AtomicInteger的用法

    J2SE 5.0提供了一组atomic class来帮助我们简化同步处理.基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增.减.赋值(更新)操作 ...

  7. 集线器(HUB),交换机,和路由器的区别

    交换机与集线器的区别从大的方面来看可以分为以下三点: 1.从OSI体系结构来看,集线器属于OSI第一层物理层设备,而交换机属于OSI的第二层数据链路层设备.也就意味着集线器只是对数据的传输起到同步.放 ...

  8. ES6 之 Set数据结构和Map数据结构 Iterator和for...of循环

    ECMAScript 6 入门 Set数据结构 基本用法 ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set本身是一个构造函数,用来生成Set数据结构. va ...

  9. 比较C++中的4种类型转换方式(转自http://blog.csdn.net/hrbeuwhw/article/details/7884797)

    C++的四种cast操作符的区别 Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意? A:转换的含义是通 ...

  10. JavaScript动态加载资源【js|css】示例代码

    在开发过程中会用到各种第三方的插件,或者自己写在单独文件中的js方法库或者css样式,在html头部总是需要写一大堆的script和link标签,如果想要自己实现动态的引入资源文件,可以使用开源的re ...