当前位置: 首页 > news >正文

【详细的springboot自动装载原理】

1.默认提供的核心配置模块

springboot提供了 spring-boot-autoconfigure模块,该模块为springboot自动配置的核心模块,它初始化好了很多我们平时需要的配置类,那么有了这些配置类就能生效了吗?得需要一个东西在启动的时候去把它加载进容器里。

2.启动配置类注解 @SpringBootApplication

  • @SpringBootApplication

打开该注解


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}
), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

该注解是个复合注解,包含了

  • @SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

这个注解触发了自动配置的过程。它实际上导入了 AutoConfigurationImportSelector 类,这个类负责决定哪些自动配置类应该被添加到应用上下文中。

这是一个复合注解,它包含了 @Configuration 注解,意味着当前类是一个配置类,可以包含一个或多个 @Bean 方法来定义组件。

  • @EnableAutoConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}

这个注解触发了自动配置的过程。它实际上导入了 AutoConfigurationImportSelector 类,这个类负责决定哪些自动配置类应该被添加到应用上下文中。

  • AutoConfigurationImportSelector
    AutoConfigurationImportSelector 类的 selectImports() 方法会返回一个字符串数组,即 factoryClassNames,这些类名代表了候选的自动配置类。这些类通常是 AutoConfigureXXX 的形式,它们会根据不同的条件(如类路径上的类、系统属性、环境变量等)来决定是否应该被激活。

3.条件注解,选择性加载

再来看这些配置类的具体实现,随便找一个
在这里插入图片描述

这些类上了使用条件注解,@Conditional**,这些条件控制了这些配置类什么时候生效,也就是说,当我们需要使用新的功能时必须引入这些依赖,导入对应的start pom, 导入之后这些配置类才会生效。

4.配置类的维护

在该依赖模块下的 META-INF/spring.factories 文件里提供了所有需要自动装配的配置类,

所有满足条件的自动配置类会通过 @Bean 方法创建并注册新的 Bean 到 Spring 容器中。

5.组件扫描

Spring Boot 会扫描标注了 @SpringBootApplication 的主类以及其子包,寻找带有 @Component、@Service、@Repository 和 @Controller 等注解的类,并将它们作为 Bean 注册到容器中。

6.依赖注入

所有注册的 Bean 将根据其定义的依赖关系进行自动装配,例如使用 @Autowired 注解。

7.源码细节

1.初始化自动配置类

 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);if (result != null) {return result;} else {try {Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");MultiValueMap<String, String> result = new LinkedMultiValueMap();while(urls.hasMoreElements()) {URL url = (URL)urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);Iterator var6 = properties.entrySet().iterator();while(var6.hasNext()) {Map.Entry<?, ?> entry = (Map.Entry)var6.next();List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));result.addAll((String)entry.getKey(), factoryClassNames);}}cache.put(classLoader, result);return result;} catch (IOException var9) {IOException ex = var9;throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", ex);}}}

2.容器启动-> 进入AutoConfigurationImportSelector->

public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {//加载所有的自动配置类AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AnnotationAttributes attributes = this.getAttributes(annotationMetadata);//获取候选配置 获取满足条件的自动配置类List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);configurations = this.removeDuplicates(configurations);//获取在springboot启动类上的排除的类 如@SpringBootApplication(scanBasePackages =             		   //{"com.crpcg.ohps.weixin"}, exclude = {RabbitAutoConfiguration.class})Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);this.checkExcludedClasses(configurations, exclusions);//移除需要排除的配置类configurations.removeAll(exclusions);configurations = this.filter(configurations, autoConfigurationMetadata);//继续往下看 下面有详细的源码this.fireAutoConfigurationImportEvents(configurations, exclusions);return StringUtils.toStringArray(configurations);}}

->进入到fireAutoConfigurationImportEvents方法

参数

configurations 自动配置类

exclusions 需要排除的配置类

源码基础补充

AutoConfigurationImportListener 会遍历这个列表,对于每一个自动配置类,它会检查该类是否满足激活条件(如 @ConditionalOnClass、@ConditionalOnBean、@ConditionalOnProperty 等)。如果条件满足,它会将该类注册为一个 Bean 定义,这样 Spring 容器就能在后续的初始化过程中创建和管理这些 Bean。

private void fireAutoConfigurationImportEvents(List<String> configurations,Set<String> exclusions) {List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();if (!listeners.isEmpty()) {AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this,configurations, exclusions);for (AutoConfigurationImportListener listener : listeners) {//继续往里面看再下面invokeAwareMethods(listener);//处理自动配置的导入和激活。 listener.onAutoConfigurationImportEvent(event);}}
}

listeners变量实例化之后的值,是一个条件判断listener
在这里插入图片描述

再往里看,执行的

private void invokeAwareMethods(Object instance) {if (instance instanceof Aware) {if (instance instanceof BeanClassLoaderAware) {((BeanClassLoaderAware) instance).setBeanClassLoader(this.beanClassLoader);}if (instance instanceof BeanFactoryAware) {((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);}if (instance instanceof EnvironmentAware) {((EnvironmentAware) instance).setEnvironment(this.environment);}if (instance instanceof ResourceLoaderAware) {((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);}}
}

在这里插入图片描述

目前处于对象创建阶段,所以进入到了BeanFactoryAware

执行完返回继续执行

listener.onAutoConfigurationImportEvent(event);
//在注册自动配置类的过程中,onAutoConfigurationImportEvent 方法会评估每个自动配置类上的条件注解,如 //@ConditionalOnClass、@ConditionalOnBean、@ConditionalOnMissingBean 等,以确定它们是否应该被实际激活。
public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {if (this.beanFactory != null) {//这个报告记录了哪些条件被评估以及它们的结果。这对于调试和理解为什么某些自动配置类被激活或未被激活是非常有用的。ConditionEvaluationReport report = ConditionEvaluationReport.get(this.beanFactory);report.recordEvaluationCandidates(event.getCandidateConfigurations());report.recordExclusions(event.getExclusions());}}

Spring Boot 会启动一个监听器,监听应用上下文的启动事件,一旦所有的 Bean 加载完毕,监听器会触发 ApplicationReadyEvent 事件,表明应用已经准备好接受请求。这样就完成了整个配置类的加载

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 异常处理和swagger使用
  • Vue3时间选择器datetimerange在数据库存开始时间和结束时间
  • 人工智能技术的分析与探讨
  • Ubuntu-文件管理器中鼠标右键添加文本文件
  • 测试面试宝典(二十八)—— 请问黑盒测试和白盒测试有哪些方法?
  • Android 生成Excel并导出全流程
  • 【JAVA】Hutool CollUtil.sort 方法:多场景下的排序解决方案
  • MYSQL 第四次作业
  • 函数调用时参数是如何从右至左入栈的
  • MySQL-视图、存储过程和触发器
  • HTML常用的转义字符——怎么在网页中写“<div></div>”?
  • ArcGIS Pro SDK (九)几何 15 转换
  • 6.3 面向对象技术-设计模式
  • C++ - 基于多设计模式下的同步异步⽇志系统
  • 如何系统的学习C++和自动驾驶算法
  • 03Go 类型总结
  • Git的一些常用操作
  • JSONP原理
  • maya建模与骨骼动画快速实现人工鱼
  • React组件设计模式(一)
  • SOFAMosn配置模型
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 区块链将重新定义世界
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 如何在GitHub上创建个人博客
  • 收藏好这篇,别再只说“数据劫持”了
  • 微信小程序:实现悬浮返回和分享按钮
  • - 转 Ext2.0 form使用实例
  • # Maven错误Error executing Maven
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (12)Linux 常见的三种进程状态
  • (2024)docker-compose实战 (9)部署多项目环境(LAMP+react+vue+redis+mysql+nginx)
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (LeetCode) T14. Longest Common Prefix
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (笔试题)分解质因式
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (含笔试题)深度解析数据在内存中的存储
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)ORM
  • .NET Micro Framework 4.2 beta 源码探析
  • .net Stream篇(六)
  • .net 获取某一天 在当月是 第几周 函数
  • .net 设置默认首页
  • .net反混淆脱壳工具de4dot的使用
  • .NET面试题(二)
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • .net中我喜欢的两种验证码
  • @Builder用法
  • @GlobalLock注解作用与原理解析
  • @hook扩展分析