【Spring Boot 应用开发】-03 自动配置

Spring Boot 自动配置特性详细介绍

为了更详细地介绍 Spring Boot 的自动配置特性,我们将从以下几个方面进行深入分析:自动配置的工作原理、常见自动配置场景及其源码分析、自定义自动配置的方法,并结合具体的实例和关键源码进行说明。

1. 自动配置工作原理

1.1 条件注解

Spring Boot 使用条件注解来决定是否创建某个 Bean。常见的条件注解包括:

  • @ConditionalOnClass:只有当类路径中存在指定的类时才生效。
  • @ConditionalOnMissingBean:只有当容器中不存在指定类型的 Bean 时才生效。
  • @ConditionalOnProperty:根据配置文件中的属性值决定是否生效。

示例:

java 复制代码
@Configuration
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder().build();
    }
}
1.2 启动器依赖

引入特定的 Starter 依赖后,Spring Boot 会自动配置与该依赖相关的组件。例如,引入 spring-boot-starter-web 后,Spring Boot 会自动配置 Tomcat 和 Spring MVC。

示例:

pom.xml 中添加以下依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. 配置文件格式

Spring Boot 支持多种配置文件格式,如 .properties.yaml。YAML 格式具有层次结构清晰、可读性强的特点。

2.1 YAML 文件示例
yaml 复制代码
server:
  port: 8080
  servlet:
    context-path: /app

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

logging:
  level:
    root: info
    org.springframework: debug

3. 自动配置的工作流程

  1. 加载配置文件 :Spring Boot 在启动时会自动加载 application.yaml 文件中的配置项。
  2. 解析配置项:将配置项解析为对应的 Java 属性,并注入到相应的 Bean 中。
  3. 应用条件注解:根据条件注解判断是否需要创建某些 Bean。
  4. 初始化组件:根据配置项和条件注解的结果,初始化并装配所需的组件和服务。

4. 常见的自动配置场景及源码分析

4.1 数据源配置

自动配置类: DataSourceAutoConfiguration

关键源码:

java 复制代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
        DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {

    @Bean
    @ConfigurationProperties("spring.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "spring.datasource.type")
    public DataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().build();
    }
}

使用示例:

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret
4.2 Web 应用配置

自动配置类: WebMvcAutoConfiguration

关键源码:

java 复制代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@Import({ WebMvcAutoConfigurationAdapter.class, HttpEncodingAutoConfiguration.class,
        HttpMessageConvertersAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
        ErrorMvcAutoConfiguration.class })
public class WebMvcAutoConfiguration {

    private final DispatcherServletPath dispatcherServletPath;

    private final ResourceProperties resourceProperties;

    private final WebMvcProperties mvcProperties;

    private final ListableBeanFactory beanFactory;

    public WebMvcAutoConfiguration(DispatcherServletPath dispatcherServletPath,
            ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
            ObjectProvider<ListableBeanFactory> beanFactory) {
        this.dispatcherServletPath = dispatcherServletPath;
        this.resourceProperties = resourceProperties;
        this.mvcProperties = mvcProperties;
        this.beanFactory = beanFactory.getIfAvailable();
    }

    // 其他配置方法...
}

使用示例:

yaml 复制代码
server:
  port: 8080
  servlet:
    context-path: /app
4.3 安全配置

自动配置类: SecurityAutoConfiguration

关键源码:

java 复制代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ SecurityContextHolder.class, AuthenticationManager.class })
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnEnabledSecurityFeature
@AutoConfigureBefore(HttpSecurityConfigurations.class)
@AutoConfigureAfter({ MetricsWebAutoConfiguration.class, MvcRequestMetricsFilterAutoConfiguration.class })
public class SecurityAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

    // 其他配置方法...
}

使用示例:

yaml 复制代码
spring:
  security:
    user:
      name: user
      password: password
4.4 缓存配置

自动配置类: CacheAutoConfiguration

关键源码:

java 复制代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheConfiguration.class)
@AutoConfigureAfter({ ContextRefreshedEvent.class, CacheConfiguration.class })
@AutoConfigureBefore({ JCacheCacheConfiguration.class, EhCacheCacheConfiguration.class,
        CaffeineCacheConfiguration.class, SimpleCacheConfiguration.class,
        CompositeCacheConfiguration.class })
public class CacheAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "spring.cache", name = "type", havingValue = "simple", matchIfMissing = true)
    public CacheManager cacheManager() {
        return new SimpleCacheManager();
    }

    // 其他配置方法...
}

使用示例:

yaml 复制代码
spring:
  cache:
    type: simple

5. 自定义自动配置

如果默认的自动配置不能满足需求,我们可以通过以下方式自定义自动配置:

5.1 编写自定义配置类

示例:

java 复制代码
@Configuration
@ConditionalOnClass(RedisTemplate.class)
public class RedisAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}
5.2 扩展现有配置

通过继承或组合的方式扩展现有的自动配置类。

示例:

java 复制代码
@Configuration
@Import(DataSourceAutoConfiguration.class)
public class CustomDataSourceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public DataSource customDataSource(DataSourceProperties properties) {
        // 自定义数据源逻辑
        return properties.initializeDataSourceBuilder().build();
    }
}
5.3 禁用自动配置

application.yaml 中使用 spring.autoconfigure.exclude 属性禁用某些自动配置类。

示例:

yaml 复制代码
spring:
  autoconfigure:
    exclude: 
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

6. 总结

Spring Boot 的自动配置特性极大地简化了开发过程,减少了繁琐的配置工作。通过合理的配置文件管理和条件注解的使用,我们可以快速构建出高效、稳定的 Spring Boot 应用程序。

而理解自动配置的工作原理和常见场景的源码实现,有助于更好地掌握 Spring Boot 的核心机制,并能够灵活应对各种实际开发需求。

后面一节,我们会针对某个Spring Boot的自动配置源码,来深入分析自动配置的原理,并手撸一个我们自己的自动配置类。

相关推荐
夕阳之后的黑夜15 分钟前
SpringBoot + 九天大模型(文生图接口)
java·spring boot·后端·ai作画
造梦师阿鹏25 分钟前
Spring Web 嵌套对象校验失效
spring boot·spring valid·spring校验
芝士就是力量啊 ೄ೨27 分钟前
Kotlin 循环语句详解
android·java·开发语言·kotlin
云端 架构师29 分钟前
Python语言的编程范式
开发语言·后端·golang
QQ274378510934 分钟前
django基于Python对西安市旅游景点的分析与研究
java·后端·python·django
会code的厨子39 分钟前
Spring底层核心原理解析
java·spring
苹果酱05671 小时前
Redis之数据结构
java·spring boot·毕业设计·layui·课程设计
程序员清风1 小时前
为什么大部分程序员成不了架构师?
后端·面试·程序员
云端 架构师1 小时前
Python语言的字符串处理
开发语言·后端·golang
造梦师阿鹏1 小时前
【SpringBoot】用一个常见错误说一下@RequestParam属性
java·spring boot·后端·spring