【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的自动配置源码,来深入分析自动配置的原理,并手撸一个我们自己的自动配置类。

相关推荐
驭渊的小故事10 分钟前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
Elastic 中国社区官方博客34 分钟前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn1881 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn1 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su2 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
码事漫谈2 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780513 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123453 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒3 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记3 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端