1.目标:熟练使用spring,并分析其源码,了解其中的思想。这篇主要介绍spring ioc 容器的加载
2.前提条件:会使用debug
3.源码分析方法:Intellj idea debug 模式下源码追溯
通过ClassPathXmlApplicationContext 进行xml 件的读取,从每个堆栈中读取程序的运行信息
4.注意:由于Spring的类继承体系比较复杂,不能全部贴图,所以只将分析源码之后发现的最主要的类继承结构类图贴在下方。
5.关于Spring Ioc Demo:我们从demo入手一步步进行代码追溯。

1.Spring Ioc Demo


1.定义数据访问接口IUserDao.java

public interface IUserDao {  public void InsertUser(String username,String password);
}

2.定义IUserDao.java实现类IUserDaoImpl.java

public class UserDaoImpl implements IUserDao {    @Override    public void InsertUser(String username, String password) { System.out.println("----UserDaoImpl --addUser----");    }
}

3.定义业务逻辑接口UserService.java

public interface UserService {    public void addUser(String username,String password);
}

4.定义UserService.java实现类UserServiceImpl.java

public class UserServiceImpl implements UserService {    private     IUserDao  userDao;    //set方法  public void  setUserDao(IUserDao  userDao) {        this.userDao = userDao;   }    @Override    public void addUser(String username,String password) { userDao.InsertUser(username,password);    }
}

bean.xml配置文件

<beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd         ">  <!--id名字自己取,class表示他代表的类,如果在包里的话需要加上包名-->    <bean id="userService"  class="UserServiceImpl" >      <!--property代表是通过set方法注入,ref的值表示注入的内容--><property  name="userDao"  ref="userDao"/>  </bean>    <bean id="userDao"  class="UserDaoImpl"/>
</beans>

2.ApplicationContext 继承结构:


1.顶层接口:ApplicationContext
2.ClassPathXmlApplicationContext实现类继承AbstractXmlApplication 抽象类
3.AbstractXmlApplication 继承AbstractRefreshableConfigApplicationContext
4.AbstractRefreshableConfigApplicationContext抽象类继承AbstractRefreshableApplicationContext
5.AbstractRefreshableApplicationContext 继承 AbstractApplicationContext
6.AbstractApplicationContext 实现ConfigurableApplicationContext 接口
7.ConfigurableApplicationContext 接口继承
ApplicationContext接口
总体来说继承实现结构较深,内部使用了大量适配器模式。
以ClassPathXmlApplicationContext为例,继承类图如下图所示:

Spring ioc .png

3.Spring Ioc容器加载过程源码详解


在开始之前,先介绍一个整体的概念。即spring ioc容器的加载,大体上经过以下几个过程:
资源文件定位、解析、注册、实例化

1.资源文件定位
其中资源文件定位,一般是在ApplicationContext的实现类里完成的,因为ApplicationContext接口继承ResourcePatternResolver 接口,ResourcePatternResolver接口继承ResourceLoader接口,ResourceLoader其中的getResource()方法,可以将外部的资源,读取为Resource类。


2.解析DefaultBeanDefinitionDocumentReader,
解析主要是在BeanDefinitionReader中完成的,最常用的实现类是XmlBeanDefinitionReader,其中的loadBeanDefinitions()方法,负责读取Resource,并完成后续的步骤。ApplicationContext完成资源文件定位之后,是将解析工作委托给XmlBeanDefinitionReader来完成的
解析这里涉及到很多步骤,最常见的情况,资源文件来自一个XML配置文件。首先是BeanDefinitionReader,将XML文件读取成w3c的Document文档。
DefaultBeanDefinitionDocumentReader对Document进行进一步解析。然后DefaultBeanDefinitionDocumentReader又委托给BeanDefinitionParserDelegate进行解析。如果是标准的xml namespace元素,会在Delegate内部完成解析,如果是非标准的xml namespace元素,则会委托合适的NamespaceHandler进行解析最终解析的结果都封装为BeanDefinitionHolder,至此解析就算完成。
后续会进行细致讲解。


3.注册
然后bean的注册是在BeanFactory里完成的,BeanFactory接口最常见的一个实现类是DefaultListableBeanFactory,它实现了BeanDefinitionRegistry接口,所以其中的registerBeanDefinition()方法,可以对BeanDefinition进行注册这里附带一提,最常见的XmlWebApplicationContext不是自己持有BeanDefinition的,它继承自AbstractRefreshableApplicationContext,其持有一个DefaultListableBeanFactory的字段,就是用它来保存BeanDefinition
所谓的注册,其实就是将BeanDefinition的name和实例,保存到一个Map中。刚才说到,最常用的实现DefaultListableBeanFactory,其中的字段就是beanDefinitionMap,是一个ConcurrentHashMap。
代码如下:
>1.DefaultListableBeanFactory继承实现关系

public class DefaultListableBeanFactory
extends
AbstractAutowireCapableBeanFactory
implements
ConfigurableListableBeanFactory,
BeanDefinitionRegistry,
Serializable { // DefaultListableBeanFactory的实例中最终保存了所有注册的bean    beanDefinitionMap/** Map of bean definition objects, keyed by bean name */private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64); //实现BeanDefinitionRegistry中定义的registerBeanDefinition()抽象方法public void registerBeanDefinition(String beanName, BeanDefinition    beanDefinition)      throws BeanDefinitionStoreException {}

>2.BeanDefinitionRegistry接口

public interface BeanDefinitionRegistry extends AliasRegistry {   //定义注册BeanDefinition实例的抽象方法void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)         throws BeanDefinitionStoreException;

4.实例化


注册也完成之后,在BeanFactory的getBean()方法之中,会完成初始化,也就是依赖注入的过程
大体上的流程就是这样,下一篇博客,再具体地从代码层面进行介绍。

博客搬家:大坤的个人博客
欢迎评论哦~

Spring Ioc 源码分析(一)--Spring Ioc容器的加载相关推荐

  1. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    概述 我们知道 Spring Boot 能够创建独立的 Spring 应用,内部嵌入 Tomcat 容器(Jetty.Undertow),让我们的 jar 无需放入 Servlet 容器就能直接运行. ...

  2. Spring Security 源码分析:Spring Security 授权过程

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring I ...

  3. Spring 源码分析(七)--bean的加载详细分析

    一:缓存中获取单例bean 前面已经提到过,单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从sing ...

  4. Spring源码分析【3】-SpingWebInitializer的加载

    SpingWebInitializer的加载 Spring基于注解的配置代码: public class SpingWebInitializer extends AbstractAnnotationC ...

  5. 【GStreamer源码分析】playbin播放test.wav加载插件过程分析

    playbin播放test.wav加载插件过程分析 一.前言 二.playbin 播放 .wav 音频插件加载一览 三.测试代码 3.1 gst_init 3.2 gst_element_set_st ...

  6. php源码哪些文件是主程序,ThinkPHP源码分析之核心类文件的加载

    研究了下TP的加载机制,以下是我的一些总结: 1.首先由应用入口文件index.php引入TP入口文件ThinkPHP.php 2.ThinkPHP.php里主要是定义一些系统常量,URL模式定义,系 ...

  7. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  8. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  9. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

最新文章

  1. 编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量,那么下列说法正确的是
  2. npj Digit. Med. | 基于人工智能的FDA批准的医疗器械和算法现状
  3. Android2.3解析json出错
  4. centos 安装搜狗输入法_Ubuntu 20.04 安装搜狗输入法
  5. go语言游戏编程初识--`Ebiten`
  6. javascript 西瓜一期 04 解释型语言与编译型语言的翻译过程
  7. 数学-矩阵计算(1)矩阵和向量的求导法则
  8. Hadoop学习总结之五:Hadoop的运行痕迹
  9. Scikit-Learn (浅谈Kmeans聚类算法)
  10. NXP K60使用IAR烧录教程
  11. 今天,我 22 岁了 ...
  12. 用阿里云商标注册流程步骤,以及有哪些商标延伸服务
  13. mysql 5.6 msvcr100_mysql 5.6.46 安装到winserver2012(x64) 遇到 MSVCR100.dll is missing
  14. android 双击返回键退出 拦截menu键
  15. Spring加载时报错处理
  16. 强化学习 Sarsa 实战GYM下的CliffWalking爬悬崖游戏
  17. vue学习记录 coderwhy d3
  18. SAP CDS UI 常用注解用法
  19. 别让用户发呆—设计中的防呆策略[转]
  20. 电商项目超详细测试点整理(一)

热门文章

  1. java命令可以但是javac命令找不到
  2. 再论CMMI和敏捷的对话
  3. 撰写实施方案注意事项
  4. java 矩形重叠问题_两个矩形重叠的问题
  5. 前端实现数字快速递增_艾默生新型超声波发生器的数字控制功能可实现快速设置和准确操作...
  6. mysql root 无法建立数据库_MySQL - 在root用户下你跟我说无法建表!?
  7. 新趋势:数据驱动的销售
  8. 周五话运营 | 做个了解用户的精细化运营喵
  9. Java中String和byte[]间的转换浅析
  10. 【树莓派编程】检测有没有物体移动 +人脸识别