Spring概述

前言

Spring 发展至现在,俨然成为一个生态,但要理解其余的 Spring Boot、Spring Cloud 等框架,需要先对 Spring 的整个体系有一定的理解,因为其余的框架都是在 Spring 框架的基础上进行的扩,当理解了 Spring 的核心之后其余的框架就很容易搞明白了,Spring 的核心在于 IOC 和 BeanDefinition,IOC容器用于存放所有的单例 Bean 和所创建单例 Bean 所需要的 BeanDefinition,其余的 AOP、事务等全部都是在此基础上进行的扩展。

此系列可能会将整体混合书写,比如:在进行 Spring 分析的时候,可能会插入一些 Spring Boot 的解析,也有可能会插入别的知识点,但大部分都不会脱离 Spring 源码的主线。

XML 的方式属于 Spring 的原生使用方式,在后期的时候扩展出了注解方式的处理,文章会从 xml 方式开始,中间会穿插注解的处理方式。其余的很多东西,大家都能在网上查到响应的资料,这里就不再过多的说明。

这里说一下整体的阅读源码的方式吧,Spring 源码前前后后翻了将近 5-6 次,最近才领略到 Spring 的魅力之所在,大致方式为先整体后细分,先全局再部分,先知道大致的一个处理流程,然后再去看其详细的部分,整个系列也是这个方式,会有一个全局的大流程贯穿,然后辅以详细的流程处理,一层一层的去看里面的处理方式。

在进行之前,建议安装一个 Translation 翻译插件,方便进行翻译。

环境搭建问题,这里不再赘述,网上有大量的教程,有问题的话,可以直接进入文章最后的群进行询问。

注意:这里假设是你已经有一定的开发经验了,很多细小的问题,可能没有注意到,如果有什么疑问,可以直接通过评论或者加群询问。

IOC总览

这里的分析主要从 ClassPathXmlApplicationContext 这个类开始,最终会调用到 refresh() 这个方法,整体会从 refresh() 这个方法作为入口进行一系列的分析,其余的 Spring Boot (AnnotationConfigServletWebServerApplicationContext) 框架,等都会调用到这个方法,所以说 refresh() 是核心方法也不为过,所以整体的脉络也不会偏离 refresh() 这个方法。

ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

此处,的 super(parent) 会调用父类的方法,加载资源解析器,

setConfigLocations(configLocations)获取系统属性和系统环境变量,对上述路径进行表达式(${})进行解析。

public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
// 调用父类构造方法,进行相关的对象创建等操作,包含属性的赋值操作
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}

refresh()方法的核心处理

public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/**
* 做容器刷新前的准备工作
* 1、设置容器的启动时间
* 2、设置活跃状态为true
* 3、设置关闭状态为false
* 4、获取Environment对象,并加载当前系统的属性值到Environment对象中
* 5、准备监听器和事件的集合对象,默认为空的集合
*/ prepareRefresh(); /**
// Tell the subclass to refresh the internal bean factory.
// 创建容器对象:DefaultListableBeanFactory
// 加载xml配置文件的属性值到当前工厂中,最重要的就是 BeanDefinition 加载、解析 xml, 形成 GenericBeanDefinition, 自定义标签的解析和默认的 bean 标签解析都在此处,解析自定义标签的时候会将 inner 类注入到 BeanDefinitionMap 中去
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
// beanFactory的准备工作,对各种属性进行填充
/** 添加一些 BeanPostProcessor,忽略某些接口,添加 SPEL 表达式解析器,注册某些特定的 bean 到 IOC 容器中去*/
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
// 子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
/**注册并调用所有的 BFPP 接口,注解的解析就是在此进行,ConfigurationClassPostProcessor 用于解析注解。*/
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
// 注册bean处理器,这里只是注册功能,真正调用的是getBean方法
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
// 为上下文初始化message源,即不同语言的消息体,国际化处理,
initMessageSource(); // Initialize event multicaster for this context.
// 初始化事件监听多路广播器
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
// 留给子类来初始化其他的bean
onRefresh(); // Check for listener beans and register them.
// 在所有注册的bean中查找listener bean,注册到消息广播器中
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的单实例(非懒加载的)
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
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.
// 为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean
destroyBeans(); // Reset 'active' flag.
// 重置active标志
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();
}
}
}

有的地方加载不出来这个图,原图位置:https://gitee.com/magic-ice/images/raw/master/images/20210309093033.png

prepareRefresh()

准备刷新

protected void prepareRefresh() {
// Switch to active.
// 设置容器启动的时间
this.startupDate = System.currentTimeMillis();
// 容器的关闭标志位
this.closed.set(false);
// 容器的激活标志位
this.active.set(true); // 记录日志
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
} // Initialize any placeholder property sources in the context environment.
// 留给子类覆盖,初始化属性资源
initPropertySources(); // Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 创建并获取环境对象,验证需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners...
// 判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到此集合中
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
// 如果不等于空,则清空集合元素对象
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
} // Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
// 创建刷新前的监听事件集合
this.earlyApplicationEvents = new LinkedHashSet<>();
}

01-Spring概述(总览)的更多相关文章

  1. 第01章 Spring概述

    第01章 Spring概述 1.Spring概述 ①Spring是一个开源框架 ②Spring为简化企业级开发而生,使用Spring,JavaBean就可以实现很多以前要靠EJB才能实现的功能.同样的 ...

  2. 黑马_13 Spring Boot:01.spring boot 介绍&&02.spring boot 入门

    13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 SpringBoot基础 1.1 原有 ...

  3. Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录

    一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...

  4. Java虚拟机JVM学习01 流程概述

    Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...

  5. Spring概述

    layout: post title: Spring概述 tags: [Java,Spring,IOC,AOP] --- Spring是一个开源的轻量级Java SE(Java 标准版本)/Java ...

  6. spring原理案例-基本项目搭建 01 spring framework 下载 官网下载spring jar包

    下载spring http://spring.io/ 最重要是在特征下面的这段话,需要注意: All avaible features and modules are described in the ...

  7. 基础知识(09) -- Spring 概述

    Spring概述-------------------------------------------------------------------------主要内容: 1.Spring是什么 2 ...

  8. Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述

    第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...

  9. 1.1 Spring 概述

    1.1 Spring 概述 1.1.1 Spring 的简史 第一阶段:xml配置 Spring 1.x时代使用xml配置Bean 第二阶段:注解配置 Spring2.x  Spring 提供了声明B ...

随机推荐

  1. 抓包 127.0.0.1 (loopback) 使用 tcpdump+wireshark

    直接使用 wireshark无法抓取 127.0.0.1环回的数据包,一种解决方法是先传到路由器再返回,但这样可能造成拥塞. Linux 先使用tcpdump抓包并输出为二进制文件,然后wiresha ...

  2. QXDM和QCAT软件使用指南

    一.传送门 链接:https://pan.baidu.com/s/1i55YXnf 密码:v6nw 二.QXDM,QPST和QCAT的简单说明 QXDM,QPST和QCAT是Qualcomm高通公司针 ...

  3. 7816协议时序和采用UART模拟7816时序与智能卡APDU指令协议

    7816时序 7816时一个比较早的老通讯时序了,最近项目上需要用UART模拟所以,简单学习时序. 时序比较简单,熟悉UART的一眼看着就像是串口的时序,只是他没有停止位,取而代之的就是保护时间gur ...

  4. 记一次小米手机安装Google Play(其他手机类似)

    记一次小米手机安装Google Play(其他手机类似) 最近换了一款小米10青春版,性价比很高,对于开发者而言,手机自带商店的软件内容往往不能满足需求,而需要单独定制习惯性的APP,博主通过最近的尝 ...

  5. Storybook 最新教程

    Storybook 最新教程 Storybook is the most popular UI component development tool for React, Vue, and Angul ...

  6. H5 CSS 悬浮滚动条

    H5 CSS 悬浮滚动条 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!

  7. css variables & CSS 变量

    css variables & CSS 变量 https://gist.github.com/xgqfrms-GitHub/5d022a13292c615d2730e84d909e1aba c ...

  8. overwrite & override

    overwrite & override explanation https://stackoverflow.com/questions/8651562/overwrite-or-overri ...

  9. PWA & TWA

    PWA & TWA https://www.bilibili.com/video/av68082979/ Service Worker workbox.js https://developer ...

  10. Flutter中mixin的使用

    页表页面 这是一个普通的展示数据,上拉加载更多数据的列表. 其中有一个类型为List<T>的数据列表listData,有个page数据用于分页,isLoading用来判断是否正在加载数据, ...