spring源码学习笔记2——基于注解生成BeanDefinition的过程解析
一丶前言
1.AnnotationConfigApplicationContext是什么
独立的应用程序上下文,接受组件类作为输入——特别是 @Configuration 注释的类,但也有普通的 @Component 类型和使用 javax.inject 注解的 JSR-330 兼容类。 允许使用 register(Class...) 逐个注册类,以及使用 scan(String...) 进行类路径扫描。 在多个@Configuration 类的情况下,后面的类中定义的@Bean 方法将覆盖早期类中定义的方法。 这可以用来通过额外的 @Configuration 类故意覆盖某些 bean 定义
2.类图
相比于ClassPathXmlApplicationContext ,AnnotationConfigApplicationContext多实现了一个接口AnnotationConfigRegistry,AnnotationConfigRegistry有两个方法
二丶两个重要的构造方法
和ClassPathXmlApplicationContext 不同的在于,在refresh之前会执行register or scan
三丶register
AnnotatedBeanDefinitionReader 看名称和 XmlBeanDefinitionReader 差不多,理论上应该实现了BeanDefinitionReader接口,但是却没有(虚晃一枪),最终调用到doRegisterBean方法
1.@Condition注解生效
ConditionEvaluator用于执行Condition注解的内容
2.@Scope 注解解析
这里使用AnnotationScopeMetadataResolver 来解析@Scope 把Scope注解上的内容 封装到ScopeMetadata 中,默认为单例,且proxyMode为不使用代理类
3.获取bean 名称
使用 AnnotationBeanNameGenerator 来获取bean名称,如果当前的BeanDefinition是 AnnotatedBeanDefinition(说明是由注解注入bean的方式)会解析@Componet(或者它的符合注解上的value值)(还支持javax.annotation.ManagedBean,javax.inject.Named)
如果没有标注bean名称,那么会生成默认的Bean名称,当前类名首字母小写对于的值
4.解析@Lazy,@Primary,@DependsOn,@Role,@Description 注解
解析注解并且设置AnnotatedBeanDefinition 对应的属性,@Lazy 表示是否懒加载(用到的时候再加载)@Primary在存在多个符合条件的bean可以注入的时候,标注@Primary注解的bean会优先被注入,@DependsOn表示这个bean的注入依赖于其他bean
5.执行BeanDefinitionCustomizer
BeanDefinitionCustomizer 接口是Spring给我们留下的一个扩展点,可以通过实现这个接口,对BeanDefinition进行自定义的设置
6.@Scope注解的proxyMode
如果标注proxyMode为ScopedProxyMode.TARGET_CLASS 表示为当前类生成CGLIB代理类,ScopedProxyMode.INTERFACES表示使用JDK动态代理,取代用户定义的Bean,如果是No 那么直接返回原BeanDefinition注册到容器
调用 ScopedProxyCreator.createScopedProxy方法,具体的做法是会把用户的BeadDefinition拷贝一份,但是还会由如下操作
7.注册BeanDefinition到容器
和xml相同,都是维护一张Map 保存Bean 名称和BeanDefinition的关系,并且维护别名
四丶scan
扫描的任务委托给ClassPathBeanDefinitionScanner 完成,主要逻辑在scanCandidateComponents方法中
1.isCandidateComponent
主要逻辑如下:
这里的excludeFilters为空集合,includeFilters存在一个AnnotationTypeFilter,可以根据类上面的注解判断是否符合条件,判断逻辑如下
一般considerInherited 为false,considerInterfaces也为false
最终判断一个类是否是候选组件的方法实在AnnotationTypeFilter的matchSelf方法
这里是否考虑合并注解是指
2.转换为ScannedGenericBeanDefinition,并且判断是否符合条件
3.后续的操作
-
解析Scope和register方法类似,都是获取注解上的Scope并设置,后面如果proxyMode不为no 还会复制当前BeanDefinition,并且设置不作为依赖注入的候选bean
-
解析@Lazy,@Primary,@DependsOn,@Role,@Description 注解
-
还会检查是否重复bean名称
如果存在名称相同的BeanDefinition,这里有个判断是否兼容的逻辑,就是BeanDefinition数据来源(比如来自注解)来源相同,或者当前BeanDefinition和存在的BeanDefinition相同 那么视为兼容,否则抛出异常
!![](https://img2022.cnblogs.com/blog/2605549/202208/2605549-20220820160530997-340329034.png)
五丶AnnotationConfigApplicationContext 的refresh操作
AnnotationConfigApplicationContext 的refresh操作后续不会加载BeanDefinition了,register or scan 负责BeanDefinition的加载了
相关文章
- EasyCVR对接华为iVS订阅摄像机和用户变更请求接口介绍
- 精选 | 腾讯云CDN内容加速场景有哪些?
- 模块化网络防止基于模型的多任务强化学习中的灾难性干扰
- 用搜索和注意力学习稳健的调度方法
- 用于多变量时间序列异常检测的学习图神经网络
- 助力政企自动化自然生长,华为WeAutomate RPA是怎么做到的?
- 使用腾讯轻量云搭建Fiora聊天室
- TSRC安全测试规范
- 云计算“功守道”
- 助力成本优化,腾讯全场景在离线混部系统Caelus正式开源
- Flink 利器:开源平台 StreamX 简介
- 腾讯云实践 | 一图揭秘腾讯碳中和?解决方案
- 深度学习中的轻量级网络架构总结与代码实现
- 信息系统项目管理师(高项复习笔记三)
- Adobe国际认证让科技赋能时尚
- c++该怎么学习(面试吃土记)
- 面试官问发布订阅模式是在问什么?
- 面试官:请实现一个通用函数把 callback 转成 promise
- 空中悬停、翻滚转身、成功着陆,我用强化学习「回收」了SpaceX的火箭
- 中山大学林倞解读视觉语义理解新趋势:从表达学习到知识及因果融合