文章目录

  • 概要
  • 1.程序入口:加载配置类
  • 2.注解配置上下文AnnotationConfigApplicationContext
  • 3.刷新上下文
  • 4.核心类AnnotationConfigApplicationContext的类图结构
  • 5.跟踪源码进入ioc

概要

​ 以前总是很忙,没有时间写博客,现在挤出时间写一些总结性及实用性的博客。

​ 首先聊一下,之所以开始看源码,是因为随着自身对java的理解不断加深,感觉自己对技术架构方面很感兴趣。所以想深入了解一下开源框架的本质,看各种开源框架、jdk源码有一段时间了,也在源码上写了很多自己理解的注释,一直没有整体总结,偶尔想起来有一些思路,但是容易忘记,所以想做一些总结,每一个我觉得非常复杂的核心流程,我都会用一张或时许图、流程图来进行学习总结。

​ 总的来说,spring的总体流程不是很复杂,但是细思极恐;每一个类、每一个方法的内部实现能牵扯出很多与之相关联的类;其中实现错综复杂,不过不管怎么难,带着设计模式的思想、以及多思考,多实践,多总结的角度,多看几遍,终归会有所收获(可以自己手绘一些uml时序图、流程图来加深理解)。

​ 本文及后续文章主要基于spring 5.0源码分析spring 核心的 ioc和aop,首先缕清spring运行的整体脉络流程。由于注解驱动(无xml)的流行,本文不会涉及xml的上下文及容器刷新流程(注意:作者之前有使用过ssm,涉及过xml配置,个人觉得xml配置会让人思想上更容易理解spring容器、bean的定义等等,感觉现在直接使用spring boot的人可能渐渐忽略了spring才是基石)。

1.程序入口:加载配置类

​ 本文主要采用AnnotationConfigApplicationContext 作为程序的起点。

public class MyApplication {public static void main(String[] args) {//spring上下文,启动一个spring应用程序。AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyApp.class);Car bean =(Car) context.getBean("car");System.out.println(bean.getColor()+bean.getPrice());}
}

2.注解配置上下文AnnotationConfigApplicationContext

AnnotationConfigApplicationContext:注解配置上下文。

 public AnnotationConfigApplicationContext(Class<?>... componentClasses) {//this()由于继承关系,所以会先调用父类的构造方法,在调用子类的构造方法/*** @Author coyhzx* @Description 类继承结构(暂不涉及接口)DefaultResourceLoader -> AbstractApplicationContext ->GenericApplicationContext -> AnnotationConfigApplicationContext*   {@link DefaultResourceLoader} 初始化当前线程的classLoader*   {@link AbstractApplicationContext} 初始化资源模式匹配解析器 PathMatchingResourcePatternResolver*   {@link GenericApplicationContext}  初始化 ioc底层容器 DefaultListableBeanFactory*   {@link AnnotationConfigApplicationContext}  初始化 reader 注解的bean的读取器,scanner 类路径的bean的扫描器**/this();//componentClasses 注册单个组件beanregister(componentClasses);//刷新容器refresh();} 

AnnotationConfigApplicationContext的无参构造this();

 public AnnotationConfigApplicationContext() {//创建一个注解的bean的读取器,猜想一下,很关键,要想读取注解,是不是要注册一些内置的BeanPostProcess后置处理器来处理注解bean。this.reader = new AnnotatedBeanDefinitionReader(this);//创建一个类路径的bean的扫描器this.scanner = new ClassPathBeanDefinitionScanner(this);}

3.刷新上下文

refresh()刷新容器

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.// 刷新上下文前的准备prepareRefresh();// Tell the subclass to refresh the internal bean factory.// 获取beanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.// beanFactory的一些准备工作prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.// 留给子类Context去实现,目前为空postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.// 调用 beanFactoryPostProcessors beanFactory的后置处理器//重点: 解析入口的配置类invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.//注册Bean的后置处理器registerBeanPostProcessors(beanFactory);// Initialize message source for this context.//初始化消息源initMessageSource();// Initialize event multicaster for this context.//初始化事件广播监听器initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.//子类初始化一些特殊的beanonRefresh();// Check for listener beans and register them.// 检查并注册监听器registerListeners();// Instantiate all remaining (non-lazy-init) singletons.//重点:完成所有非延迟加载bean的初始化finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.//完成上下文刷新finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

​ 简单来说:整体流程其实已经走完了,感觉有点走马观花,但是其中每一个方法每一个new对象,每一个父子继承的实现其实很复杂。得慢慢梳理。先看一下AnnotationConfigApplicationContext得类图,从图中可以看成,spirng把一个上下文的接口抽象出来了很多顶级接口,和抽象类和实现类,看多了很多源码,摸清楚了一些spring框架的一些小特点,通常spring接口会有顶级接口,定义规范,抽象类实现接口的公用方法,具体的特性交给不同实现类去实现,这里着重介绍一些核心得关键接口和类。

4.核心类AnnotationConfigApplicationContext的类图结构

BeanFactory: Bean工厂的顶级接口。里面定义了变量factorbean的前缀&,getBean()、getType()、是否单例、是否原型的方法等等。

ResourceLoader: 资源加载的顶级接口。很简单,里面仅仅定义了classpath的url,getClassLoader()、getResource(String location)方法。
DefaultResourceLoader:默认的资源加载类。加载classpath下的资源文件。

AbstractApplicationContext:抽象的上下文类。实现了可配置的上下文接口ConfigurableApplicationContext,是一个很重要的类,refresh()刷新容器的主要逻辑就在其中。

GenericApplicationContext:广泛普通的上下文类。我们真正底层的ioc容器,bean工厂DefaultListableBeanFactory就是在它的初始化中创建的。

AnnotationConfigApplicationContex:注解配置的上下文类。很关键,是可以直接定位加载注解配置类的上下文。

BeanDefinitionRegistry:bean的注册接口。定义了注册bean、移除bean等接口。

5.跟踪源码进入ioc

​ 先简单的介绍AnnotationConfigApplicationContext#register(componentClasses)方法,以及跟踪源码,可以直接进入我们常说的ioc容器之中,看着上下文是如何帮我们在上下文中创建一个BeanDefinition,并放入容器中。

​ 好了,尽管我省略了很多细节,但是整体的配置类BeanDefinition注册流程通过下图展示,spring在ioc容器中注册了bean的定义了,那么如何去完成实例化bean的实例呢,请期待我下一篇文章把!

下一篇:2、spring源码解析之单例bean的实例化

1、spring源码解析之概况流程相关推荐

  1. Spring源码解析【完整版】--【bilibili地址:https://www.bilibili.com/video/BV1oW41167AV】

    [本文为bilibili视频雷丰阳的Spring源码解析的完整版总结文章,其中文章前面大部分为他人博文的搬运,后面补充了其未总结的部分] 一.Java的注解 1. 注解的概念 注释:用文字描述程序,给 ...

  2. Spring源码解析之-- 事务TransactionInterceptor 分析(开启事务)

    目录 一.介绍 二.TransactionInterceptor 分析 2. 流程 2.1 invoke 2.1.1 TransactionAspectSupport#invokeWithinTran ...

  3. Spring源码——声明式事务流程

    前言 最近回顾了一下Spring源码,准备用思维导图的方式简单的将整个源码内容的流程展示出来,思维导图.图片等文件更新在https://github.com/MrSorrow/spring-frame ...

  4. Spring源码解析之@Component注解的扫描

    阅读须知 Spring源码版本:4.3.8 文章中使用/* */注释的方法会做深入分析 正文 承接Spring源码解析之context:component-scan标签解析,下面就是扫描的流程: Cl ...

  5. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    2019独角兽企业重金招聘Python工程师标准>>> 我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegi ...

  6. Spring源码解析:自定义标签的解析过程

    2019独角兽企业重金招聘Python工程师标准>>> spring version : 4.3.x Spring 中的标签分为默认标签和自定义标签两类,上一篇我们探究了默认标签的解 ...

  7. Retrofit2源码解析——网络调用流程(下)

    Retrofit2源码解析系列 Retrofit2源码解析(一) Retrofit2源码解析--网络调用流程(上) 本文基于Retrofit2的2.4.0版本 implementation 'com. ...

  8. android 输入法如何启动流程_android输入法02:openwnn源码解析01—输入流程

    android 输入法 02:openwnn 源码解析 01-输入流程 之后要开始 android 日文输入法的测试,因此现在开始研究 android 输入法.之前两 篇文章已经对 android 自 ...

  9. Spring 源码解析 -- SpringWeb过滤器Filter解析

    简介 在上几篇文章中探索了请求处理相关的代码,本篇开始探索请求处理前的一些操作代码,如Filter.本篇探索Filter初始化.请求处理等相关代码. 前言 说先简单的定义相关的测试代码: 启动类: i ...

  10. Spring源码解析 -- SpringWeb请求参数获取解析

    Spring源码解析 – SpringWeb请求参数获取解析 简介 在文章:Spring Web 请求初探中,我们看到最后方法反射调用的相关代码,本篇文章就探索其中的参数是如何从请求中获取的 概览 方 ...

最新文章

  1. 1120. Friend Numbers (20)
  2. 相互靠近的色环电感之间的互感
  3. 210328卡式水分开阶段总结
  4. 5 个最受人喜爱的开源 Django 包
  5. 打砖块小游戏php程序,利用原生js实现html5打砖块小游戏(代码示例)
  6. oracle排名怎么去除空值影响,Oracle排序中null值处理方法讲解
  7. 1107: 回文数猜想(函数专题)
  8. 编写react组件_如何编写第一个React.js组件
  9. PHP--金额数字转换成英文
  10. python sqlite row
  11. 向量范数证明例题_第八课:向量的范数
  12. c#转换XML文件和json对象
  13. HTML5 Canvas vs. SVG vs. div
  14. 数据结构与算法中的经典算法
  15. ip地址块的聚合,计算其聚合后的可用地址数
  16. html设计判断闰年,javascript如何判断是否为闰年?
  17. C#——初识Console
  18. 字节跳动校招提前批前端一面总结
  19. HHUOJ 1395 彩票
  20. 男人二十岁后应该学会的习惯 - 褪墨

热门文章

  1. 万亿市场的广场舞未来在哪里?
  2. 5.8Gwifi信道
  3. MAVEN下载修改settings.xml
  4. 华为 荣耀 等手机解锁BootLoader
  5. LPDDR4的ZQ 校准
  6. 4k hidpi 黑苹果_黑苹果开启缩放分辨率HiDPi以及字体模糊的调整方法总结
  7. python FTPS使用ftplib下载文件(详细)
  8. ShuffleNet原理
  9. Solidity编程语言
  10. android mtk 常用修改器,MTK android 可修改IMEI方法