coldsmog开发笔记
JS 事件笔记
Ckeditor 上传WPS图片失败问题
Springboot
SpringBoot 统一异常处理
Springboot 引入外部jar包
Springboot 打成war包
Springboot 多环境配置
SpringBoot @Scope注解学习
Springboot 快速生成项目API文档
SpringCache 缓存
Spring jetcache 二级缓存
Springboot 按条件装配类
FastJson的JsonPath语法
正则表达式语法
Spring 路径匹配
Feign 基础数据操作
监控Feign调用metrics
Springboot feign的性能优化
Jackson 设置序列化属性
SpringBoot 集成 Spring Data Mongodb 操作 MongoDB
MongoDB 的一些注意事项
MongoDB 指令对比
Jackson 解析XML
Springboot Redis注册
SpringBoot RedisTemplate批量插入
Springboot 指标监控Micrometer
springboot validation 注解校验
springboot 引入配置
Springboot 静态文件处理
Springboot 导出csv文件
Springboot 事件驱动(发布/订阅模式)
Springboot 启动过程和扩展点
Springboot 优化停机上下线
Spring自动装配 - 干饭角度学习
Springboot ShardingJDBC
Springboot的重试
springboot 动态修改端口
Oracle
Oracle 中实现自增ID
Oracle 定时任务
Oracle 解锁临时表
Oracle 检查连接数
Oracle 表空间
Oracle 解释执行SQL
markdown作图(适用typora)
服务器压测
业务对象层和数据层
并发限流处理
中间件
Yarn的使用
Dubbo学习笔记-RPC扩展和本地Mock
Dubbo学习笔记-泛化实现进行mock
Redis缓存穿透,缓存击穿,缓存雪崩
Galera 集群说明
Pip 镜像
pip 使用
MySQL命令行
数据库缓存双写方案
Git相关操作
Redis 操作时间复杂度一览
nacos 杂记
mybatis 散记
shardingjdbc
一次线上事故排查发现的Caffeine缓存死锁问题
设计模式
重新讲讲单例模式和几种实现
更优雅地实现策略模式
Http-headers
Prometheus 杂散笔记
JAVA 散记
CompletableFuture
Gson、FastJson、Jackson、json-lib对比总结
jackson 时间的序列化踩坑
JVM
自定义注解
mysql类型和java类型 转换一览表
枚举维护一个Map<value, Enum>的映射
Java中String +、concat、StringBuilder、StringBuffer 性能对比
TraceId 使用
MySQL 多数据源处理
Mybatis-plus 流式查询
JAVA发送win 桌面通知
idea 启动项目失败非代码问题杂记
Lambda 简述
Arthas 使用笔记
一种链式更新数据的数据模式
Skywalking 新增中间件插件
Redission 使用
数据导出为图片
IDEA 的热重启
Netty 工具类
maven 插件
本文档使用 MrDoc 发布
-
+
首页
Spring自动装配 - 干饭角度学习
## 什么是Spring的自动装配 Spring框架的一个核心功能是IoC(控制反转),管理着应用程序中的对象及其依赖关系。在没反转前,我们写应用需要自己知道并初始化依赖实例,然后再使用依赖实例。反转后,应用只需要告诉spring需要什么依赖接口,spring自己会找注册了该接口的依赖实例提供给我们。控制权从使用方反转到了提供方。 从干饭角度理解:当我们需要一份筷子(依赖实例)干饭时,并不需要关心筷子是怎么生产出来的,而是去食堂(Spring)领一份就行。我们只需要告诉食堂,我需要是筷子而不是刀叉(声明依赖接口),那么食堂就会帮我们准备好一份筷子。 Spring自动装配就是Spring自动识别和注入组件依赖关系的步骤。 干饭角度理解:食堂帮我从仓库识别筷子、找到一份筷子、提供筷子的一系列步骤。 这个场景在应用上非常常见: 引入spring-boot-starter-data-redis并配置链接信息后,我们直接就能在service中引入RedisTemplate 并使用。 ## SpringBoot2.X 自动装配是如何完成的? SpringBoot 2.X 的启动入口main函数,有个注解 @SpringBootApplication,它通过@EnableAutoConfiguration 的@Import,将AutoConfigurationImportSelector收集到的全类名注册成bean。 ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage // 关键在这个 @Import引入其他start里通过Configuration注册的Bean, 也就是先把筷子存入仓库 @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { // 可以配置修改是否自动装配,默认true String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; } ``` 从import的处理见 ConfigurationClassParser::processImports。 我们重点关注AutoConfigurationImportSelector的收集过程。 ```java // 注意是延迟导入,所以用DeferredImportSelector懒加载 public class AutoConfigurationImportSelector implements DeferredImportSelector { protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); // 加载到所有自动装配的全类名,收集的是所有 Spring Boot Starter下的 META-INF/spring.factories List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); // 过滤不满足 @ConditionalOnXXX 条件的启动类。比如过年才给用红筷子,就能这么限制过滤。 configurations = getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); } } ``` 从上面可以看到,SpringBoot 通过SPI的方式,约定了 Spring Boot Starter只要resource下有 META-INF/spring.factories 就能帮忙注册成Bean 一个简单的spring.factories如下 ```yaml # Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.autoconfigure.BackgroundPreinitializer # Environment Post Processors org.springframework.boot.env.EnvironmentPostProcessor=\ org.springframework.boot.autoconfigure.integration.IntegrationPropertiesEnvironmentPostProcessor # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener # Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ org.springframework.boot.autoconfigure.condition.OnBeanCondition,\ org.springframework.boot.autoconfigure.condition.OnClassCondition,\ org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition # 一般我们只需要这个,指向我们的@Configuration的类,这样就能正常使用里面注册的依赖实例了。 # 是的,厂商提供筷子也得通过标准的@Bean提供,这部分各依赖各自实现,需要的话啃他们源码吧,祝大家吃饱。 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\ com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration ``` ## SpringBoot3.X 的自动装配? 很遗憾,我们的干饭之旅不是那么顺利,如果我们追求吃口热乎饭,就会发现 spring.factories功能在Spring Boot 2.7标识废弃,在Spring Boot 3.0彻底移除 升级方案是 文件从`META-INF/spring.factories` 换成 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports` ```ymal # 拆分成单独文件,故不需要前面的 xxx.EnableAutoConfiguration=, 同时格式换成一个全类名一行,不再用逗号拼接 com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration ``` 参考资料: https://www.cnblogs.com/throwable/p/16950353.html https://javaguide.cn/system-design/framework/spring/spring-boot-auto-assembly-principles.html
寒烟濡雨
2024年2月22日 20:24
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码