SpringBoot自动配置深入探究实现原理

作者:飘飘~ 时间:2023-08-06 09:59:58 

说明:在阅读本篇文章之前建议大家先详细学习一下spring的相关知识,有助于更深刻的理解spirngboot的配置原理。

一、什么是springboot自动配置

SpringBoot通过@EnableAutoConfiguration注解开启自动配置,对jar包下的spring.factories文件进行扫描,这个文件中包含了可以进行自动配置的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化,注册到Spring容器中。

通俗的来讲,我们之前在写ssm项目时候,配置了大量坐标和配置内容,搭环境的过程在项目开发中占据了大量时间,SpringBoot的最大的特点就是简化了各种xml配置内容,所以springboot的自动配置就是用注解来对一些常规的配置做默认配置,简化xml配置内容,使你的项目能够快速运行。

springboot核心配置原理:

  • 自动配置类都存放在spring-boot-autoconfigure-版本号.jar下的org.springframework.boot.autoconfigure中

  • 当我们在application.properties中配置debug=true后启动容器。可以看到服务器初始化的初始化配置

  • DispatcherServletAutoConfigratio注册前端控制器

  • EmbeddedServletContainerAutoConfiguration注册容器类型

  • HttpMessageConvertersAutoConfiguration注册json或者xml处理器

  • JacksonAutoConfiguration注册json对象解析器

  • 如果加入其他功能的依赖,springBoot还会实现这些功能的自动配置

SpringBoot自动配置深入探究实现原理

二、Starter组件

Starter组件是可被加载在应用中的Maven依赖项项。只有在Maven配置中添加对应的依赖配置,即可使用对应的Starter组件。例如,添加spring-boot-starter-web依赖,就可以用于构建RESTAPI服务,其包含了SpringMVC和Tomcat内嵌容器。

一个完整的Starter组件包括以下两点:

  • 提供自动配置功能的自动配置模块

  • 提供依赖关系管理岗功能的组件模块,即封装了组件所有功能,开箱即用。

spring-boot-starter-web依赖源码

package org.springframework.boot.autoconfigure.web.servlet;
@Configuration
@ConditionalOnClass({ServletRequest.class})
@ConditionalOnWebApplication(
   type = Type.SERVLET
)
@EnableConfigurationProperties({ServerProperties.class})
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class})
public class ServletWebServerFactoryAutoConfiguration {
   ......
}
@

三、三大注解

@SpringBootConfiguration:继承自Configuration,支持JavaConfig的方式进行配置。

@EnableAutoConfiguration:本文重点讲解,主要用于开启自动配置。

@ComponentScan:自动扫描组件,默认扫描该类所在包及其子包下所有带有指定注解的类,将它们自动装配到bean容器中,会被自动装配的注解包括@Controller、@Service、@Component、@Repository等。也可以指定扫描路径。

四、@EnableAutoConfiguration

这个注解是帮助我们自动加载默认配置的,它里面有两个关键注解@AutoConfigurationPackage和@Import,我们来详细了解@Import注解。

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//检查自动配置功能是否开启,默认开启
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//加载自动配置的元信息
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取候选配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//去掉重复的配置类
configurations = removeDuplicates(configurations);
//获得注解中被exclude和excludeName排除的类的集合
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//检查被排除类是否可实例化、是否被自动注册配置所使用,不符合条件则抛出异常
checkExcludedClasses(configurations, exclusions);
//从候选配置类中去除掉被排除的类
configurations.removeAll(exclusions);
//过滤
configurations = filter(configurations, autoConfigurationMetadata);
//将配置类和排除类通过事件传入到 * 中
fireAutoConfigurationImportEvents(configurations, exclusions);
//最终返回符合条件的自动配置类的全限定名数组
return StringUtils.toStringArray(configurations);

@Import(AutoConfigurationImportSelector.class)注解,这里导入AutoConfigurationImportSelector类。这个类中有一个非常重要的方法&mdash;&mdash;selectImports(),它几乎涵盖了组件自动装配的所有处理逻辑,包括获得候选配置类、配置类去重、排除不需要的配置类、过滤等,最终返回符合条件的自动配置类的全限定名数组。

五、SpringFactoriesLoader

spring-core包里定义了SpringFactoriesLoader类,这个类实现了检索META-INF/spring.factories文件,并获取指定接口的配置的功能。在这个类中定义了两个对外的方法:

  • loadFactories根据接口类获取其实现类的实例,这个方法返回的是对象列表。

  • loadFactoryNames根据接口获取其接口类的名称,这个方法返回的是类名的列表。

上面的两个方法的关键都是从指定的ClassLoader中获取spring.factories文件,并解析得到类名列表,具体代码如下:

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
   String factoryClassName = factoryClass.getName();
   try {
       Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
               ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
       List<String> result = new ArrayList<String>();
       while (urls.hasMoreElements()) {
           URL url = urls.nextElement();
           Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
           String factoryClassNames = properties.getProperty(factoryClassName);
           result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
       }
       return result;
   }
   catch (IOException ex) {
       throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
               "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
   }
}

由代码可知,在这个方法中会遍历整个ClassLoader中所有jar包下的spring.factories文件。也就是说我们可以在自己的jar中配置spring.factories文件,不会影响到其它地方的配置,也不会被别人的配置覆盖。

spring.factories的是通过Properties解析得到的,所以我们在写文件中的内容都是安装下面这种方式配置的:

com.xxx.interface=com.xxx.classname

最后希望大家在学习的过程中,能够多了解实现各种功能的基本原理,有助于提高学习效率。

来源:https://blog.csdn.net/m0_46420244/article/details/126320109

标签:SpringBoot,自动配置
0
投稿

猜你喜欢

  • Spring 与 JDK 线程池的简单使用示例详解

    2023-08-20 04:02:59
  • Java String类常用方法梳理总结

    2021-08-22 17:57:03
  • SpringBoot实战之高效使用枚举参数(原理篇)案例详解

    2022-02-10 23:54:23
  • C#如何绑定多个按钮到同一个事件

    2022-09-09 16:20:12
  • java获取时间的方法总结

    2022-03-28 15:36:38
  • Java 中Timer和TimerTask 定时器和定时任务使用的例子

    2022-04-21 17:50:27
  • Android单选按钮对话框用法实例分析

    2023-03-27 17:10:52
  • 浅谈C# 构造方法(函数)

    2021-11-23 08:01:49
  • 关于C# 类的封装详情

    2023-11-29 05:38:20
  • Android中SurfaceView用法简单实例

    2022-01-05 20:10:11
  • C#使用ICSharpCode.SharpZipLib.dll进行文件的压缩与解压功能

    2022-01-09 15:30:45
  • 提示出现unresolved external symbol _main的解决方法

    2023-02-13 03:41:48
  • Java判断所给年份是平年还是闰年

    2023-10-21 17:48:59
  • Java如何将二维数组转化为一维数组

    2022-11-18 12:23:18
  • 一文详解Spring security框架的使用

    2023-06-03 22:42:09
  • Jar包冲突问题原理及解决方案

    2023-03-05 09:40:02
  • C# Winform按钮中图片实现左图右字的效果实例

    2022-05-01 12:51:41
  • C# dump系统lsass内存和sam注册表详细

    2021-06-26 12:19:53
  • 详解如何将Spring Boot应用跑在Docker容器中

    2023-04-25 08:08:58
  • Spring Boot非Web项目运行的方法

    2021-07-23 13:05:32
  • asp之家 软件编程 m.aspxhome.com