自动配置概述

SpringBoot的两大核心

Spring Boot 框架的两大核心特性可以概括为“启动器”(Starter)和“自动配置”(Auto-configuration)。

  1. 启动器(Starter)
    Spring Boot 提供了一系列的 Starter POMs,它们是一组预定义的依赖关系。

当你在项目中引入一个 Starter POM 时,它会自动包含所有必要的 Spring 组件以及合理的默认设置。开发者不需要手动管理复杂的依赖关系,也不需要担心版本冲突的问题,减少了配置上的出错可能。

  1. 自动配置(Auto-Configuration)
    当添加了特定的 Starter POM 后,Spring Boot 会根据类路径上存在的 jar 包来自动配置 Bean(自动配置相关组件)(比如:SpringBoot发现类路径上存在mybatis相关的类,例如SqlSessionFactory.class,那么SpringBoot将自动配置mybatis相关的所有Bean)。

如果开发者没有显式地提供任何与特定功能相关的配置,Spring Boot 将使用其默认配置来自动设置这些功能。当然,如果需要的话,用户也可以覆盖这些默认设置。

这两个特性结合在一起,使得使用 Spring Boot 开发应用程序变得更加简单快速,减少了大量的样板代码和重复配置的工作。让程序员专注业务逻辑的开发,在环境方面耗费最少的时间。

体会自动配置带来的便捷

拿SpringBoot集成MyBatis为例。

以前,在没有SpringBoot框架的时候,我们用Spring集成MyBatis框架,需要进行如下的配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 数据源配置 -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <!-- SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.example.model"/>
    </bean>

    <!-- Mapper 扫描器 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.example.mapper"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 开启事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- 扫描 service 层的包 -->
    <context:component-scan base-package="com.example.service"/>

</beans>

通过以上的配置可以看到Spring集成MyBatis的时候,需要手动提供BasicDataSourceSqlSessionFactoryBeanMapperScannerConfigurerDataSourceTransactionManager等Bean的配置。

使用了Spring Boot框架之后,这些配置都不需要提供了,SpringBoot框架的自动配置机制可以全部按照默认的方式自动化完成。减少了大量的配置,在环境方面耗费很少的时间,让程序员更加专注业务逻辑的处理。我们只需要在application.yml中提供以下的配置即可:

1
2
3
4
5
6
7
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot
    username: root
    password: 123456
    type: com.zaxxer.hikari.HikariDataSource

引入web启动器都有哪些组件会准备好

通过以下代码获取spring ioc容器中的所有注册的bean,一个Bean就是一个组件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package com.powernode.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class TestApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(TestApplication.class, args);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        applicationContext.close();
    }

}

在springboot没有引入任何启动器的情况下,默认提供了59个bean:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
mbeanExporter
objectNamingStrategy
mbeanServer
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.internalConfigurationPropertiesBinder
org.springframework.boot.context.properties.BoundConfigurationProperties
org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar.methodValidationExcludeFilter
spring.jmx-org.springframework.boot.autoconfigure.jmx.JmxProperties
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
springApplicationAdminRegistrar
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration
forceAutoProxyCreatorToUseClassProxying
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
applicationAvailability
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration
lifecycleProcessor
spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
spring.sql.init-org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties
org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor
org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration
fileWatcher
sslPropertiesSslBundleRegistrar
sslBundleRegistry
spring.ssl-org.springframework.boot.autoconfigure.ssl.SslProperties
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration
threadPoolTaskExecutorBuilder
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorBuilderConfiguration
taskExecutorBuilder
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration
simpleAsyncTaskExecutorBuilder
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorConfiguration
applicationTaskExecutor
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties
org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$ThreadPoolTaskSchedulerBuilderConfiguration
threadPoolTaskSchedulerBuilder
org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$TaskSchedulerBuilderConfiguration
taskSchedulerBuilder
org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration
simpleAsyncTaskSchedulerBuilder
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties
org.springframework.aop.config.internalAutoProxyCreator

引入web启动器:

1
2
3
4
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

可以发现,ioc容器中注册的bean总数量为160个:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration
fileWatcher
sslPropertiesSslBundleRegistrar
sslBundleRegistry
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.internalConfigurationPropertiesBinder
org.springframework.boot.context.properties.BoundConfigurationProperties
org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar.methodValidationExcludeFilter
spring.ssl-org.springframework.boot.autoconfigure.ssl.SslProperties
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration
websocketServletWebServerCustomizer
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat
tomcatServletWebServerFactory
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
servletWebServerFactoryCustomizer
tomcatServletWebServerFactoryCustomizer
server-org.springframework.boot.autoconfigure.web.ServerProperties
webServerFactoryCustomizerBeanPostProcessor
errorPageRegistrarBeanPostProcessor
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration
dispatcherServlet
spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration
dispatcherServletRegistration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration
threadPoolTaskExecutorBuilder
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorBuilderConfiguration
taskExecutorBuilder
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration
simpleAsyncTaskExecutorBuilder
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorConfiguration
applicationTaskExecutor
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration
error
beanNameViewResolver
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration
conventionErrorViewResolver
spring.web-org.springframework.boot.autoconfigure.web.WebProperties
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
errorAttributes
basicErrorController
errorPageCustomizer
preserveErrorControllerTargetClassPostProcessor
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
welcomePageHandlerMapping
welcomePageNotAcceptableHandlerMapping
localeResolver
themeResolver
flashMapManager
mvcConversionService
mvcValidator
mvcContentNegotiationManager
requestMappingHandlerMapping
mvcPatternParser
mvcUrlPathHelper
mvcPathMatcher
viewControllerHandlerMapping
beanNameHandlerMapping
routerFunctionMapping
resourceHandlerMapping
mvcResourceUrlProvider
defaultServletHandlerMapping
requestMappingHandlerAdapter
handlerFunctionAdapter
mvcUriComponentsContributor
httpRequestHandlerAdapter
simpleControllerHandlerAdapter
handlerExceptionResolver
mvcViewResolver
mvcHandlerMappingIntrospector
viewNameTranslator
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter
defaultViewResolver
viewResolver
requestContextFilter
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
formContentFilter
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
mbeanExporter
objectNamingStrategy
mbeanServer
spring.jmx-org.springframework.boot.autoconfigure.jmx.JmxProperties
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
springApplicationAdminRegistrar
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration
forceAutoProxyCreatorToUseClassProxying
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
applicationAvailability
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration
standardJacksonObjectMapperBuilderCustomizer
spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration
jacksonObjectMapperBuilder
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration
parameterNamesModule
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration
jacksonObjectMapper
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonMixinConfiguration
jsonMixinModuleEntries
jsonMixinModule
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
jsonComponentModule
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration
lifecycleProcessor
spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration
stringHttpMessageConverter
org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration
mappingJackson2HttpMessageConverter
org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
messageConverters
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
spring.sql.init-org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties
org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor
org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$ThreadPoolTaskSchedulerBuilderConfiguration
threadPoolTaskSchedulerBuilder
org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$TaskSchedulerBuilderConfiguration
taskSchedulerBuilder
org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration
simpleAsyncTaskSchedulerBuilder
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties
org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration
httpMessageConvertersRestClientCustomizer
restClientSsl
restClientBuilderConfigurer
restClientBuilder
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
restTemplateBuilderConfigurer
restTemplateBuilder
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration
tomcatWebServerFactoryCustomizer
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
characterEncodingFilter
localeCharsetMappingsCustomizer
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
multipartConfigElement
multipartResolver
spring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties
org.springframework.aop.config.internalAutoProxyCreator

也就是说,引入了web启动器后,ioc容器中增加了101个bean对象(加入了101个组件)。这101个bean对象都是为web开发而准备的,例如我们常见的:

  • dispatcherServlet:DispatcherServlet 是 Spring MVC 的前端控制器,负责接收所有的 HTTP 请求,并将请求分发给适当的处理器(Controller)
  • viewResolver:ViewResolver 是 Spring MVC 中用于将逻辑视图名称解析为实际视图对象的组件。它的主要作用是根据控制器返回的视图名称,找到对应的视图实现(如 JSP、Thymeleaf、Freemarker 等),并返回给 DispatcherServlet 用于渲染视图。
  • characterEncodingFilter:字符集过滤器组件,解决请求和响应的乱码问题。
  • mappingJackson2HttpMessageConverter:负责处理消息转换的组件。它可以将json字符串转换成java对象,也可以将java对象转换为json字符串。
  • ……

每一个组件都有它特定的功能。

没有使用SpringBoot之前,以上的很多组件都是需要手动配置的。

默认的包扫描规则

之前我们已经说过并且测试过:springboot默认情况下只扫描主入口类所在包及子包下的类。

这是因为@SpringBootApplication注解被@ComponentScan标注,代替spring以前的这个配置:<context:component-scan base-packages="主入口类所在包"/>

当然,我们也可以打破这个规则,通过以下两种方式:

  • 第一种:@SpringBootApplication(scanBasePackages = “com”)
  • 第二种:@ComponentScan(“com”)
1
2
3
4
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com")
public class TestApplication {}

默认配置

springboot为功能的实现提供了非常多的默认配置.

例如:tomcat服务器端口号在没有配置的情况下,默认是8080

当然,也可以在application.properties文件中进行重新配置:

1
server.port=8081

再如,配置thymeleaf的模板引擎时,默认的模板引擎前缀是classpath:/templates/,默认的后缀是.html

当然,也可以重新配置:

1
2
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

这些配置最终都会通过@ConfigurationProperties(prefix="")注解绑定到对应的bean的属性上。这个Bean我们一般称为属性类。例如:

ServerProperties:服务器属性类,专门负责配置服务器相关信息。

1
2
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {}

ThymeleafProperties:Thymeleaf属性类,专门负责配置Thymeleaf模板引擎的。

1
2
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {}

SpringBoot官方文档当中也有指导,告诉你都有哪些属性类,告诉你在application.properties中都可以配置哪些东西。默认值都是什么:

自动配置是按需加载的

SpringBoot提供了非常多的自动配置类,有的是web相关的自动配置,有的是mail相关的自动配置。但是这些自动配置并不是全部生效,它是按需加载的。导入了哪个启动器,则该启动器对应的自动配置类才会被加载

这些自动配置类在哪里?

任何启动器都会关联引入这样一个启动器:spring-boot-starter,它是springboot框架最核心的启动器。

spring-boot-starter又关联引入了spring-boot-autoconfigure。所有的自动配置类都在这里。

SpringBoot框架提供的条件注解

如何做到按需加载的,依靠SpringBoot框架中的条件注解来实现的。

Spring Boot框架中的@ConditionalOnXxx系列注解属于条件注解(Conditional Annotations),它们用于基于某些条件来决定是否应该创建一个或一组Bean。这些注解通常用在自动配置类上,以确保只有在特定条件满足时才会应用相应的配置。

这里是一些常见的@ConditionalOnXxx注解及其作用:

  • @ConditionalOnClass:当指定的类存在时,才创建Bean。
  • @ConditionalOnMissingClass:当指定的类不存在时,才创建Bean。
  • @ConditionalOnBean:当容器中存在指定的Bean时,才创建Bean。
  • @ConditionalOnMissingBean:当容器中不存在指定的Bean时,才创建Bean。
  • @ConditionalOnProperty:当配置文件中存在指定的属性时,才创建Bean。也可以设置属性值需要匹配的值。
  • @ConditionalOnResource:当指定的资源存在时,才创建Bean。
  • @ConditionalOnWebApplication:当应用程序是Web应用时,才创建Bean。
  • @ConditionalOnNotWebApplication:当应用程序不是Web应用时,才创建Bean。

使用这些注解可以帮助开发者根据不同的运行环境或配置来灵活地控制Bean的创建,从而实现更智能、更自动化的配置过程。这对于构建可插拔的模块化系统特别有用,因为可以根据实际需求选择性地启用或禁用某些功能。

假设我们来实现这样一个功能:如果IoC容器当中存A,就创建BBean,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Configuration
public class AppConfig {

    @Bean
    public A a(){
        return new A();
    }

    @ConditionalOnBean(A.class)
    @Bean
    public B b(){
        return new B();
    }
}

如果IoC容器当中不存在ABean,就创建BBean,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Configuration
public class AppConfig {

    @Bean
    public A a(){
        return new A();
    }

    @ConditionalOnMissingBean(A.class)
    @Bean
    public B b(){
        return new B();
    }
}

当类路径当中存在DispatcherServlet类,则启用配置,反之则不启用配置,代码如下:

1
2
3
4
5
6
7
8
@ConditionalOnClass(name = {"org.springframework.web.servlet.DispatcherServlet"})
@Configuration
public class MyConfig {
    @Bean
    public A getA(){
        return new A();
    }
}

以上程序自行测试!

自动配置实现原理

我们来深入的分析一个问题:为什么导入web启动器,web开发相关的自动配置就会生效?

在程序没有开始执行之前都导入了哪些依赖

在程序没有开始运行之前,我们先来分析一下,当导入web启动器之后,底层都一连串的导入了哪些依赖!

  1. 从这里开始:导入了spring-boot-starter-web【web启动器】
  2. 然后关联导入了spring-boot-starterspring-boot-starter-jsonspring-boot-starter-tomcatspring-webspring-webmvc
    1. 注意:spring-boot-starter是springboot核心启动器,任何启动器在导入时,都会关联导入springboot核心启动器。
  3. 核心启动器导入之后,关联导入了一个jar包:spring-boot-autoconfigure
    1. 注意:这个jar包中存放的是springboot框架**官方支持的自动配置类**。如下图:

2. 官方支持的自动配置类有多少个呢,可以通过下图位置查看:

得知springboot3.3.5这个版本共152个自动配置类。自动配置类的命名规则是XxxxAutoConfiguration

提示:哪个自动配置类生效,就代表哪个配置文件生效,那么对应的技术就完成了整合,就可以进行对应技术的开发。

从main方法开始执行之后都发生了什么

以上分析的是在项目结构上已经完成了相关依赖的导入,这些自动配置了导入到了项目当中,那么在运行时哪些自动配置类会被加载?哪些自动配置类会生效呢?我们接下来进行程序运行阶段的分析:

  1. 程序从main方法进入执行,主入口类上使用@SpringBootApplication进行了标注。
  2. @SpringBootApplication注解是复合注解,代表以下三个注解的功能:
    1. @SpringBootConfiguration:它被@Configuration标注,说明主入口类就是一个配置类,此时该配置开始加载。
    2. @ComponentScan:默认扫描的是主入口所在包以及子包。因此spring-boot-autoconfigure包是扫描不到的,按说XxxAutoConfiguration自动配置类是无法加载的!!!那么这些自动配置类又是如何加载和生效的呢?
    3. @EnableAutoConfiguration:自动配置类的加载和生效全靠它了。该注解被翻译为:启用自动配置。
  3. @EnableAutoConfiguration@Import(AutoConfigurationImportSelector.class)标注
    1. @Import(AutoConfigurationImportSelector.class)的作用是:将AutoConfigurationImportSelector作为一个Bean加载到IoC容器中。
    2. 这个Bean的作用是:负责收集和选择所有符合条件的自动配置类。
  4. 添加断点,跟踪AutoConfigurationImportSelector源码:

通过跟踪得知,这152个自动配置类的类名都会被加载到IoC容器中。注意:加载了152,并不是152个全部生效

  1. 152个自动配置类底层是怎么查找的?

通过以上源码跟踪,得知,是从下图位置加载的:

  1. 最终哪些自动配置类生效了?

最先获取到152个,经过上图的一层一层的过滤(条件注解),最终筛选了26个自动配置类,为什么这么少,因为你只引入了web starter。这26个配置就是做web开发需要的最少配置。

具体怎么排除的,请看以下解释:

  • configurations = removeDuplicates(configurations);

去重:移除 configurations 列表中的重复项,确保每个配置类只出现一次。

  • Set<String> exclusions = getExclusions(annotationMetadata, attributes);

获取排除列表:从注解元数据和属性中获取需要排除的配置类名称集合。因为@EnableAutoConfiguration注解还能这么用:@EnableAutoConfiguration(exclude = {排除列表}, excludeName = {排除列表})

  • checkExcludedClasses(configurations, exclusions);

检查排除:验证 configurations 中是否有被排除的类,如果有,可能会抛出异常或记录警告。

  • configurations.removeAll(exclusions);

移除排除项:从 configurations 列表中移除所有在 exclusions 集合中的配置类。

  • configurations = getConfigurationClassFilter().filter(configurations);

过滤配置类:使用 ConfigurationClassFilter 对 configurations 进行进一步过滤。这一行通过条件注解进行判断,例如 @ConditionalOnClass、@ConditionalOnMissingBean 等。

  • fireAutoConfigurationImportEvents(configurations, exclusions);

触发事件:触发自动配置导入事件,通知其他组件或监听器关于最终确定的配置类和排除的类。

自动配置类都干了啥

自动配置类导入了一堆相关的组件(一个组件一个功能),而每个组件获取配置时都是从属性类中获取,而属性类恰好又和配置文件绑定。

DispatcherServletAutoConfiguration自动配置类为例,这个自动配置类主要是配置了SpringMVC中的前端控制器。

请看源码:

通过以上源码得知,DispatcherServletConfiguration组件的配置信息来源于WebMvcProperties属性类。WebMvcProperties类源码如下:

通过以上源码又得知,要对DispatcherServletConfiguration进行配置的话,应该在application.properties中使用这样的前缀配置:spring.mvc....

再来看嵌入式Web服务器工厂自定义程序自动配置EmbeddedWebServerFactoryCustomizerAutoConfiguration,通俗讲:通过它可以配置web服务器。

请看源码:

通过以上源码得知,这个自动配置类中也有很多组件,有tomcat组件,有jetty组件。单独看Tomcat,要配置Tomcat服务器,需要参照ServerProperties属性类,打开源码看看:

因此配置Tomcat服务器需要在application.properties文件中使用这样的前缀配置:server.

总结自动配置原理

  1. 运行环境准备阶段
    1. 引入web启动器
    2. 最终传递引入了自动配置的jar包
    3. 自动配置的jar包中有152个自动配置类,到此运行环境准备完毕。
  2. 运行阶段
    1. @EnableAutoConfiguration 启用自动配置,将152个自动配置类全部加载到IoC容器中,然后根据开发场景筛选出必须的自动配置类。
    2. 自动配置类加载了一堆组件。
    3. 每个组件需要的数据来自属性类。
    4. 属性类又和配置文件绑定在一起。
  3. 因此,最终一句话:导入启动器,修改配置文件,就可以完成对应功能的开发。