- 搭建Spring5.3.x源码阅读环境
- Spring Farmework 中的设计模式应用
- 实例化Bean过程
- 在不同阶段执行不同的事件,怎么办?
- Spring中的重要接口
- refresh()方法包含spring启动的核心流程,在AbstractApplication类中。
- prepareRefresh()刷新前的准备工作
- obtainFreeshBeanFactory()获取Bean工厂
- prepareBeanFactory()准备Bean工厂
- postProcessBeanFactory()
- invokeBeanFactoryPostProcessors() 执行所有注册的BFPP Bean
- registerBeanPostProcessors() 实例化并注册所有BPP
- initMessageSource()国际化操作
- initApplicationEventMulticaster() 初始化事件广播器
- onRefresh()
- registerListeners() 注册监听器
- finishBeanFactoryInitialization() 实例化所有剩下的非懒加载单例对象
- 三级缓存为了解决循环依赖
- #四、源码时序图">#四、源码时序图
- #查看完整文章">#查看完整文章
:::info 前置知识:设计模式、数据结构、jvm、多线程、反射
注意事项:
- 不专注细节
- 画图(时序图、流程图、总结图)
- 看注释(类、接口、方法)
- 见名知义
- 大胆猜测小心验证
- 坚持
:::
搭建Spring5.3.x源码阅读环境
[实战]从零到一搭建Spring 5.3.x版本源码本地搭建_哔哩哔哩_bilibili
Spring Farmework 中的设计模式应用
适配器模式:AbstractXmlApplicationContext中的loadBeanDefinitions方法
实例化Bean过程
在不同阶段执行不同的事件,怎么办?
观察者模式:监听器,监听事件,多播器
Spring中的重要接口
refresh()方法包含spring启动的核心流程,在AbstractApplication类中。
prepareRefresh()刷新前的准备工作
- 初始化系统启动时间,一些标志位
- 创建Enviroment对象
- 准备监听器和事件集合对象(用于方便扩展)
obtainFreeshBeanFactory()获取Bean工厂
子类实现
- 创建DefualtListableBeanFactory
- (加载xml文件)
prepareBeanFactory()准备Bean工厂
- 设置类加载器、SPEL解析器
- 忽略Aware实现类的注入
postProcessBeanFactory()
子类实现
invokeBeanFactoryPostProcessors() 执行所有注册的BFPP Bean
- 执行所有注册的BeanFactoryPostProcessor对象 先执行排序的(Ordered)再执行未排序的
registerBeanPostProcessors() 实例化并注册所有BPP
- 实例化并注册所有BeanPostProcessor Bean 后续执行BPP的准备工作
initMessageSource()国际化操作
小项目用不到
initApplicationEventMulticaster() 初始化事件广播器
准备工作
onRefresh()
空方法 子类实现
registerListeners() 注册监听器
准备工作
finishBeanFactoryInitialization() 实例化所有剩下的非懒加载单例对象
- 初始化类型转换操作相关参数
- 判断beanfactory有无内置值处理器
- 处理AOP织入相关操作
- 设置临时ClassLoader
- 冻结不修改的Bean
- 实例化所有非懒加载单例对象
- 遍历beanDefinitionName
- (合并子类和父类的Bean定义信息
- (doGetBean 获取或者创建Bean
- 获取BeanNames
- 从三级缓存中获取Bean
- 缓存中没有对象则开始创建Bean
- 尝试解决循环依赖问题
- 获取父类容器
- 标志位已创建对象
- 获取并检测beanDefinition
- 如果有依赖Bean递归创建依赖的Bean
- doCreateBean 实例化和初始化对象
- 使用反射实例化对象
- 处理循环依赖
- 填充属性
- 执行Aware接口方法
- 执行BeanPostProscessor:before方法
- 执行init方法
- 执行BeanPostProscessor:after方法
- 注册销毁对象方法
- 加入一级缓存
- 如果该Bean是FactoryBean,则通过其getObject再创建一个Bean
:::info 子类对象创建时父类对象也要创建,所以创建子类时会调用父类的构造函数。所以我们遇到new有父类的对象时,需要查看父类的构造函数,看父类构造函数做了什么,调用了什么方法。
:::
ClassPathXmlApplicationContext
一系列父类初始化 初始化一些属性AbstractApplicationContext
类初始化- 创建一些对象,包括
id
上下文唯一标识、active``closed
标志位、monitor
锁 - 创建了一个资源模式处理器
PathMatchingResourcePatternResolver
- 此类初始化
- 创建Ant表达式匹配处理器
- 设置父容器
- 创建一些对象,包括
AbstractXmlApplicationContext
初始化- 设置标志位
validating
用于验证配置文件
- 设置标志位
ClassPathXmlApplicationContext
初始化- 设置配置文件路径
setConfigLocations()
,方便后续直接调用- 进行一些解析处理,例如检查存在,替换占位符等。创建
StandardEnvironment
使用其中的属性,替换占位符
- 进行一些解析处理,例如检查存在,替换占位符等。创建
- 设置配置文件路径
- 调用
**refresh**
方法- 加锁
startupShutdownMonnitor
- prepareRefresh()刷新前的准备工作
- 初始化一些属性
initPropertySources()
可以做一些扩展操作,如设置所需属性,后续验证是否存在- 获取Environment,并验证所需属性是否存在
- 设置application监听器集合、设置事件集合 spring中不需要 在spring boot中需要
- obtainFreshBeanFactory
- 刷新Bean工厂设置属性、xml文件
- 创建 DefaultListableBeanFactory
- allowCircularReferences = true 自动解决循环依赖
- ignoreDependencyInterface Aware类
- 设置父类Bean工厂
- 生成容器唯一id
- customizeBeanactory()
- loadBeaDefinitions() 使用代理模式
- doRegisterBeanDefinitions()
- parseBeanDefinitionElement()
- 创建 DefaultListableBeanFactory
- 刷新Bean工厂设置属性、xml文件
- 加锁
AbstractRefreshableConfigApplicationContext
中有一个configLocations
之后会用
**StandardEnvironment**
初始化过程
调用无显示定义的无参构造方法,调用父类AbstractEnvironment
构造方法 因为没有显示定义,所以要在父类构造方法处打断点,才能查看具体流程
设置忽略属性值spring.getenv.ignore
激活的属性文件spring.profiles.active
默认属性文件spring.profiles.default
等等一些初始化工作
回到StandardEnvironment
执行customizePropertySources
方法
设置systemEnvironment
(操作系统环境变量)systemProperties
(jvm系统属性)
Environment=Property(配置)+Profile(环境)
**PathMatchingResourcePatternResolver**
实现接口**ResourceLoader**
用于加载资源
BeanFactory相关接口、类、方法
- ListableBeanFactory 可以枚举所有Bean实例
- ConfigurableBeanFactory 提供配置Bean工厂的一些方法
- HierarchicalBeanFactory 使Bean工厂具有继承关系
- DefaultListableBeanFactory 使用较多
- doGetBean() 每次操作时先从父工厂中获取 主要存在于Spring MVC中
Java的初始化顺序规则:
- 父类成员变量默认初始化
- 父类显示初始化和父类初始化块
- 父类构造器 如果使用
super()
显示调用必须放在子类构造器第一行 - 子类成员变量默认初始化
- 子类显式初始化和子类初始化块
- 子类构造器
三级缓存为了解决循环依赖
@Configuration
标注到类上,启动Spring就会自动注册Bean到Ioc容器
自动执行@Bean方法,将Bean定义信息注册到IOC容器
可以代替applicationContext.xml
文件
value bean的id
本质上是@Component
这个类中可以使用Bean Autowired Inject Resource 等注解注入所需Bean对象
AnnotationConfigApplicationContext
使用包路径- this 创建scanner reader
- doScan 扫描指定包
- scanCandidateComponents扫描候选类
- processCommonDefinitionAnnotations处理注解
- registerBeanDefinition 将beanName和BeanDefinition放入beanDefinitionMap和beanDefinitionNames
- registerAnnotationConfigProcessors注册所有相关注解后置处理器
- refresh刷新容器
- invokeBeanFactoryPostProcessors运行所有BFPP
- ConfigurationClassPostProcessor enhanceConfigurationClasses 增强配置类,使其可以对Bean方法进行拦截
ConfigurationClassPostProcessor
解析Configuration注解
BeanFactoryPostProcessors
BeanDefinitionRegistryPostProcessors 注册新的Bean
@Bean
将当前方法的返回值注入到IOC容器中
获取Bean
AbstractApplicationContext 通用上下文实现 invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate 处理和和注册后置处理器 invokeBeanFactoryPostProcessors
AbstractBeanFactory 创建和缓存Bean doGetBean
DefaultSingletonBeanRegistry 管理单例 bean getSingleton
AbstractAutowireCapableBeanFactory 用于默认Bean创建 createBean doCreateBean createBeanInstance instantiateBean
SimpleInstantiationStrategy 用于 BeanFactory 的简单对象实例化策略 instantiate
BeanUtil instantiateClass
@Import
注解使用场景:配置较多,使用import进行分类管理。引入第三方类。
ImportSelector 用于组合配置类 ImportBeanDefinitionRegistrar用于加载Bean定义
BeanFactoryPostProcessor 在Bean定义加载后进行修改
BeanDefinitionRegistryPostProcessor 动态注册新的Bean定义火大规模修改Bean定义 在其他BeanFactoryPostProcessor之前执行
ConfigurationClassPostProcessor 解析处理类及其注解 proessConfigBeanDefinitions postProcessBeanDefinitionRegistry processConfigBeanDefinitions
ConfigurationClassParser 配置类解析器 doProcessConfigurationClass parse processImports处理Impot注解
ImportSelector selectImports 获取想要注入的类的类名 需要自己实现
将配置类解析为ConfigurationClass
ConfigurationClassBeanDefinitionReader 读取ConfigurationClass类,注册其中的Bean定义 loadBeanDefinitions
AnnotationMetadata 带有注解的类的元数据
DefaultListableBeanFactory 实现BeanDefinitionRegistry注册储存Bean定义的功能。实现BeanFactory获取Bean的功能
DefaultSingletonBeanRegistry 储存单例对象
@PropertySource
加载配置文件,将配置文件放到环境变量中
PropertySourceRegistry processPropertySource
DefaultPropertySourceFactory 加载配置文件 createPropertySource
PropertiesPropertySource 封装Properties作为属性源
PropertySourceProcessor 属性源处理 addPropertySource
@ComponentScans
扫描对应包下标注@Component注解、@Configuration注解等等注解的类。
@ComponentScan 注解用于指定 Spring 扫描组件的范围。
ComponentScanAnnotationParser 解析@ComponentScan注解 parse
ClassPathBeanDefinitionScanner 扫描类路径下的Bean定义,注册到容器 registerBeanDefinition
ClassPathScanningCandidateComponentProvider 在类路径下扫描
@DependsOn
指定当前Bean对象所依赖的其他Bean对象
可以改变实例化顺序
AnnotatedBeanDefinitionReader (读取和解析配置类)和 ClassPathBeanDefinitionScanner (扫描包下的类)都是 Spring Framework 中用于注册 Bean 定义的类
注册Bean
AnnotatedBeanDefinitionReader doRegisterBean 从注解中读取元数据设置到BeanDefinition中,在注册到容器中
BeanDefinition 接口:管理Bean属性和元数据
调用后置处理器
@Conditional
将满足条件的Bean注册到容器中
使用场景:
- 需要在不同环境运行,读取不同的配置信息
ConditionEvaluator 评估是否符合条件 shouldSkip
ConfigurationClassParser processConfigurationClass 中使用shouldSkip跳过配置类
@Lazy
优化启动性能
AbstractApplicationContext preInstantiateSingletons 在此时Lazy没有被实例化
@Component
将自己创建的类注入到IOC容器中
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd) 处理以下注解:@Lazy、@Primary、@DependsOn、@Role、@Description 这些注解将会被设置到元数据中
ConfigurationClassParser doProcessConfigurationClass 处理以下注解:@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean、default方法、配置类的父类
ConfgurationClassPostProcessor processConfigBeanDefinitions
ConfigurationPhase 也就是PARSE_CONFIGURATION阶段会忽略配置类,REGISTER_BEAN阶段忽略普通类
ClassPathBeanDefinitinScanner doScan 扫描指定包
ClassPathScanningCandidateComponentProvider addCandidateComponentsFromIndex 使用componentsIndex加载组件类 scanCandidateComponents直接扫描指定包加载组件类
componentsIndex的加载过程涉及读取由构建工具(如Maven或Gradle)生成的类路径索引文件(通常是META-INF/spring.components)
@Value
由后置处理器BeanPostProcessor处理
AbstractAutowireCapableBeanFactory populateBean 填充属性
initializeBean 初始化Bean 执行Aware接口、执行BeanPostProcessor:Before、执行初始化方法、BeanPostProcessor:After
AbstractAutowireCapableBeanFactory 有自动装配功能的Bean工厂 populateBean填充属性
AutowiredAnnotationBeanPostProcessor 处理通过@Autowire和@Value注入属性 postProcessProperties
InjectionMetadata inject 遍历成员,注入属性
DefaultListableBeanFactory doResolveDependency 解决依赖@Autowired、@Value
QualifierAnnotationAutowireCandidateResolver 解析给定Bean是否是合适的自动装配候选者
- isAutowireCandidate
- getSuggestedValue
- determineAUtowireCandidate
- getLazyResolutionProxyIfNecessary
StandardBeanExpressionResolver evalutate
SpelExpression getValue
SpelNodeImpl 其实现表示各种操作符 getValue
StandardEvaluationContext spel运算上下文
@Autowire
自动按照类型注入
行AutowiredTest类
运行AutowiredTest类的main()方法,输出的结果信息如下所示。1
autowiredDao===>>>io.binghe.spring.annotation.chapter12.dao.AutowiredDao@1ba9117e
autowiredService=>>>AutowiredService{autowiredDao=io.binghe.spring.annotation.chapter12.dao.AutowiredDao@1ba9117e}
@冰河: 代码已经复制到剪贴板
2 可以看到,打印了从IOC容器中获取到的AutowiredDao类的Bean对象和AutowiredService类的Bean对象,并且向AutowiredService类中注入的AutowiredDao类的Bean对象和直接从IOC容器中获取的AutowiredDao类的Bean对象是同一个对象。