概要

Spring Boot 的自动配置(auto-configuration)是 Spring Boot 框架中一个非常重要的特性,可以大幅度简化 Spring 应用程序的配置和开发。其核心思想是根据应用程序所依赖的 jar 包和类路径上的资源,自动配置和装配 Spring 应用程序所需要的各种组件和配置

Spring Boot 的自动配置原理可以简述为以下几个步骤:

  1. Spring Boot 应用启动时,会通过类路径扫描机制,扫描所有的 jar 包,找到其中的 Spring Boot Starter 组件。

  2. Spring Boot Starter 组件中包含了一些预定义的配置类,这些配置类使用 Spring 的@Configuration注解标记,并通过条件注解@ConditionalOnClass@ConditionalOnBean等判断条件控制是否需要生效。

  3. 根据条件判断,自动配置组件会在 Spring 应用程序启动时自动被装配进 Spring 容器中。

  4. 自动配置的组件通常会使用 Spring 的@ConditionalOnMissingBean注解,如果用户已经显式地定义了同类型的 bean,那么自动配置的组件就不会生效,保证了用户自定义配置的优先级。

  5. 用户可以通过自定义配置类,通过使用 Spring 的@Import注解导入自定义的配置类来覆盖和扩展默认的自动配置。

Spring Boot 自动配置是基于 Spring 框架提供的条件注解机制实现的。当 Spring Boot 应用启动时,会根据应用的依赖和配置信息,自动选择和配置相应的 Bean。Spring Boot 的自动配置是基于以下条件注解实现的:

  • @ConditionalOnBean:当指定的Bean存在时,才会进行自动配置。

  • @ConditionalOnMissingBean:当指定的Bean不存在时,才会进行自动配置。

  • @ConditionalOnClass:当指定的类存在时,才会进行自动配置。

  • @ConditionalOnProperty:当指定的属性满足指定条件时,才会进行自动配置。

  • @ConditionalOnWebApplication:当应用是一个Web应用时,才会进行自动配置。

Spring Boot Starter

以 spring-boot-starter-web 为例,该 Starter 包含了一组 Web 应用程序所需要的各种组件和配置,包括 Tomcat 容器、Spring MVC 框架、Jackson JSON 解析器等。

在该 Starter 包中,META-INF/spring.factories文件中定义了一组自动配置类,例如:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration

这些自动配置类会在应用程序启动时自动被装配进 Spring 容器中

示例

下面我们来看一下 Spring Boot 自动配置的源代码实现。以配置 MyBatis 作为示例,我们一起来分析一下 Spring Boot 自动配置的实现过程。

首先,我们在 Maven 项目中添加 MyBatis 依赖:

<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.2.0</version>
</dependency>

Mybatis Spring Boot Starter 包含了 Mybatis 自动配置类,可以方便地将 Mybatis 集成到我们的 Spring Boot 应用中。那么,它的自动配置类是如何实现的呢?我们可以查看 mybatis-spring-boot-autoconfigure 模块下的 AutoConfiguration 类。

在 Spring Boot 启动过程中,会扫描 mybatis-spring-boot-autoconfigure 模块下的META-INF/spring.factories文件,其中会配置 AutoConfiguration 类。源代码如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

我们可以看到,这里配置的 MybatisAutoConfiguration 类就是 Mybatis 的自动配置类。接着,我们来看看 MybatisAutoConfiguration 的源代码:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnBean({ DataSource.class })
@EnableConfigurationProperties(MybatisProperties.class)
public class MybatisAutoConfiguration {
    private final MybatisProperties properties;
    private final Interceptor[] interceptors;
    private final ResourceLoader resourceLoader;

    public MybatisAutoConfiguration(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader) {
        this.properties = properties;
        this.interceptors = interceptorsProvider.getIfAvailable();
        this.resourceLoader = resourceLoader;
    }
    
    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        // ...
    }
}

可以看到,MybatisAutoConfiguration 类上使用了@Configuration注解,表明它是一个配置类。@EnableConfigurationProperties注解将 MybatisProperties 类引入到 Spring 容器中,方便我们使用配置文件中的属性。

MybatisAutoConfiguration 类构造函数中的 MybatisProperties 和ObjectProvider<Interceptor[]>参数分别用来处理 Mybatis 的配置信息和拦截器信息。接着,使用@Bean注解将 sqlSessionFactory 方法引入到 Spring 容器中,这样在应用中就可以通过@Autowired来注入 SqlSessionFactory 对象了。

当然,MybatisAutoConfiguration 类中还有很多其他的方法,用来配置 Mybatis 的各种其他参数。

接下来,我们将通过一个实例来演示如何使用 Spring Boot 的自动配置功能。

在我们的实例中,我们将使用 Spring Boot 自动配置 JdbcTemplate。JdbcTemplate 是 Spring 框架提供的一种比较简单易用的 JDBC 工具。我们只需要将相应的依赖添加到 Maven 项目中:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

然后,我们就可以使用 JdbcTemplate 啦!Spring Boot 会根据我们的依赖自动配置 DataSource 和 JdbcTemplate,让我们不需要复杂的配置就能使用 JdbcTemplate。

下面是示例代码:

@Autowired
private JdbcTemplate jdbcTemplate;
public void query() {
    List<Map<String, Object>> list = jdbcTemplate.queryForList("SELECT * FROM user");
    ...
}

我们只需要将 JdbcTemplate 注入到 Spring 容器中,然后就可以愉快地使用它了。当然,在实际应用中,我们还需要对数据源进行配置,这里我们使用默认的 H2 数据库进行演示。

src/main/resources目录下,我们创建application.properties文件,并添加数据库连接配置:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

接着,我们就可以使用 JdbcTemplate 进行查询操作了。这里我们只是简单演示一下,更多 JdbcTemplate 的使用方法可以参考官方文档。

@EnableAutoConfiguration 注解

@EnableAutoConfiguration注解是 Spring Boot 自动配置机制的入口点,它会启用 Spring Boot 的自动配置机制,并根据当前应用程序所依赖的 jar 包和类路径上的资源,自动装配各种组件和配置。

@EnableAutoConfiguration注解的实现代码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    //...
}

该注解通过@Import注解导入了 EnableAutoConfigurationImportSelector 类,这个类是自动配置机制的核心实现,负责加载META-INF/spring.factories文件中的自动配置类,并将它们注入 Spring 容器中。

自动配置类

自动配置类是 Spring Boot 自动配置机制的核心,它使用 Spring 的@Configuration注解标记,定义了一组默认的 bean 配置和组件装配规则。

例如,spring-boot-autoconfigure 包中的 WebMvcAutoConfiguration 自动配置类中,就定义了一组默认的 Spring MVC 框架组件和属性配置,包括 ViewResolver、MessageConverter、RequestMappingHandlerMapping 等。

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
    //...
}

自动配置类中通常使用 Spring 的@Conditional注解进行条件判断,根据条件判断的结果来控制是否需要生效。常见的条件注解包括@ConditionalOnClass@ConditionalOnMissingBean@ConditionalOnProperty等。

自动配置类的实现中,通常会通过 Spring 的@Import注解,导入其他的配置类和组件。例如,WebMvcAutoConfiguration 自动配置类中,就导入了一组 WebMvcConfigurationSupport 类型的配置类,用于配置 Spring MVC 框架中的各种组件和属性。

总的来说,Spring Boot 自动配置机制的核心就是基于条件注解和类路径扫描机制,在应用程序启动时自动装配各种组件和配置。通过 Starter 包的定义,Spring Boot 可以实现对各种功能模块的自动配置,大大简化了应用程序的开发和部署。

总结

Spring Boot 自动装配(Auto Configuration)是其核心特性之一,它极大地简化了基于 Spring 的应用开发,使得开发者不需要显式地定义大量的配置。以下是 Spring Boot 自动装配的基本原理和关键概念的总结:

启用自动配置

自动配置机制默认在 Spring Boot 应用中启用,主要通过 @SpringBootApplication 注解来启动。@SpringBootApplication 是三个注解的组合:

  • @SpringBootConfiguration:标记类为 Spring 配置类,等同于 @Configuration

  • @EnableAutoConfiguration:启动自动配置。

  • @ComponentScan:扫描并注册特定包下的组件。

自动配置类

Spring Boot 提供了一系列的自动配置类,这些类通常位于 org.springframework.boot.autoconfigure.* 包下。每个自动配置类负责对特定技术栈或框架的配置,例如 WebMvcAutoConfiguration 对于 Spring MVC 的配置,DataSourceAutoConfiguration 对于数据源的配置。

条件注解

自动配置类使用条件注解来决定是否应该激活。这些注解包括:

  • @ConditionalOnClass:只有在类路径上存在指定的类时才激活配置。

  • @ConditionalOnMissingBean:只有在上下文中不存在指定类型的 Bean 时才激活配置。

  • @ConditionalOnProperty:根据是否存在某个属性或其值来激活配置。

  • @ConditionalOnWebApplication@ConditionalOnNotWebApplication:根据是否是 Web 应用程序来激活配置。

  • @ConditionalOnJava:根据 Java 版本来激活配置。

自定义自动配置

开发者也可以创建自己的自动配置类。只需要使用 @Configuration 注解定义配置类,并使用条件注解来控制激活条件。同时,可以使用 @EnableAutoConfiguration@ImportAutoConfiguration 来导入其他的自动配置类。

配置属性绑定

Spring Boot 自动配置还会尝试绑定应用程序属性文件中的配置项到自动配置类中定义的组件。这是通过 @ConfigurationProperties 注解完成的,它能自动将配置文件中的属性映射到 Java Bean 属性上。

排除自动配置

如果不想使用某些自动配置,可以在 @SpringBootApplication@EnableAutoConfiguration 注解中使用 exclude 属性来排除不需要的自动配置类。

启动类

Spring Boot 的启动类通常是应用的入口点,它通常带有 @SpringBootApplication 注解。这个类会启动 Spring 应用上下文,加载配置,以及激活自动配置。

通过以上机制,Spring Boot 能够自动检测应用的环境和依赖,并提供合理的默认配置,从而减少了大量手动配置的工作量。