01-Spring概述(总览)
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概述(总览)的更多相关文章
- 第01章 Spring概述
第01章 Spring概述 1.Spring概述 ①Spring是一个开源框架 ②Spring为简化企业级开发而生,使用Spring,JavaBean就可以实现很多以前要靠EJB才能实现的功能.同样的 ...
- 黑马_13 Spring Boot:01.spring boot 介绍&&02.spring boot 入门
13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 SpringBoot基础 1.1 原有 ...
- Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录
一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...
- Java虚拟机JVM学习01 流程概述
Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...
- Spring概述
layout: post title: Spring概述 tags: [Java,Spring,IOC,AOP] --- Spring是一个开源的轻量级Java SE(Java 标准版本)/Java ...
- spring原理案例-基本项目搭建 01 spring framework 下载 官网下载spring jar包
下载spring http://spring.io/ 最重要是在特征下面的这段话,需要注意: All avaible features and modules are described in the ...
- 基础知识(09) -- Spring 概述
Spring概述-------------------------------------------------------------------------主要内容: 1.Spring是什么 2 ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述
第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...
- 1.1 Spring 概述
1.1 Spring 概述 1.1.1 Spring 的简史 第一阶段:xml配置 Spring 1.x时代使用xml配置Bean 第二阶段:注解配置 Spring2.x Spring 提供了声明B ...
随机推荐
- c#记两个变量进行值交换
今天腊月二十九啦,无心上班,专注划水.然后就在那里翻帖子消磨时光. 看到了这样一个问题,有人提问为什么 a=b+(b=a)*0 ??? 第一眼看上去,我也有点蒙,仔细推敲了一下,嗯~的确是交换了 ...
- MySQL 语句及其种类
DDL(Data Definition Language) DDL(Data Definition Language),数据定义语言 CREATE:创建数据库和表等对象 DROP:删除数据库和表等对象 ...
- 334A Candy Bags
A. Candy Bags time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- codeforces 7B
B. Memory Manager time limit per test 1 second memory limit per test 64 megabytes input standard inp ...
- php 文件包含base64读取文件 preg_replace函数
解题部分题目来源攻防世界web高手进阶区1.拿到题目以后,发现是一个index.php的页面,并且设备-没有显示完全,此位置可疑.2.源代码中发现?page=index,出现page这个get参数,联 ...
- Keras读取保存的模型时, 产生错误[ValueError: Unknown activation function:relu6]
Solution: from keras.utils.generic_utils import CustomObjectScope with CustomObjectScope({'relu6': k ...
- tfrecords转图片存储
import os import shutil import tensorflow as tf import time import sys import cv2 # 图片存放位置 PATH_RES ...
- CSS 检测 IE 浏览器
CSS 检测 IE 浏览器 <!--[if IE]> <link href="ie.css" rel="stylesheet"> < ...
- HTML script tag type all in one
HTML script tag type all in one script type https://developer.mozilla.org/en-US/docs/Web/HTML/Elemen ...
- Github Actions All In One
Github Actions All In One https://github.com/features/actions https://github.com/marketplace?type=ac ...