2812 字
约 9 分钟
1
⚙️ SpringBoot AutoConfig
2026-09-19
无标签

⚙️ 第11章 SpringBoot AutoConfig

深入理解自动配置机制和条件注解 💻 查看完整代码 - 在线IDE体验 学习目标

📋 学习目标

  • 自动配置原理- 理解SpringBoot自动配置机制
  • 条件注解- 掌握@Conditional系列注解
  • 配置类编写- 创建自定义自动配置
  • Starter开发- 开发自定义Starter
  • 配置属性- 使用@ConfigurationProperties
  • 调试技巧- 自动配置调试和排查

自动配置核心概念

🔍 自动配置核心概念

  • @EnableAutoConfiguration- 启用自动配置
  • @AutoConfiguration- 自动配置类
  • @Conditional- 条件装配
  • spring.factories- 配置文件
  • @ConfigurationProperties- 属性绑定
  • AutoConfigurationImportSelector- 导入选择器

自动配置依赖

📦 自动配置依赖配置

<!-- pom.xml 自动配置依赖 -->
<dependencies>
    <!-- SpringBoot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    
    <!-- 自动配置处理器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
    
    <!-- 配置处理器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    
    <!-- 条件注解支持 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-conditional</artifactId>
    </dependency>
</dependencies>

# application.yml 自动配置相关配置
spring:
  # 应用基本信息
  application:
    name: autoconfig-demo
    
  # 自动配置调试
  main:
    # 显示自动配置报告
    show-banner: true
    # 允许Bean定义覆盖
    allow-bean-definition-overriding: true
    
# 自定义配置属性
custom:
  service:
    # 是否启用自定义服务
    enabled: true
    # 服务名称
    name: "Custom Service"
    # 超时时间
    timeout: 30000
    # 重试次数
    retry-count: 3
    # 配置列表
    endpoints:
      - name: "endpoint1"
        url: "http://localhost:8081"
      - name: "endpoint2"
        url: "http://localhost:8082"

# 日志配置
logging:
  level:
    # 显示自动配置日志
    org.springframework.boot.autoconfigure: DEBUG
    # 显示条件评估日志
    org.springframework.boot.autoconfigure.condition: TRACE
    cn.bugstack.springframework.boot.autoconfig: DEBUG

自动配置流程

🔄 自动配置流程

1启动扫描 @EnableAutoConfiguration触发自动配置扫描 2加载配置类 从spring.factories文件加载自动配置类 3条件评估 根据@Conditional注解评估是否满足条件 4Bean注册 满足条件的配置类注册Bean到容器 5属性绑定 @ConfigurationProperties绑定配置属性 6完成装配 所有自动配置完成,应用启动 自动配置实现

🎯 自动配置实现

// CustomServiceProperties.java - 配置属性类
@ConfigurationProperties(prefix = "custom.service")
@Data
public class CustomServiceProperties {
    
    /**
     * 是否启用自定义服务
     */
    private boolean enabled = true;
    
    /**
     * 服务名称
     */
    private String name = "Default Service";
    
    /**
     * 超时时间(毫秒)
     */
    private long timeout = 30000;
    
    /**
     * 重试次数
     */
    private int retryCount = 3;
    
    /**
     * 端点配置列表
     */
    private List<Endpoint> endpoints = new ArrayList<>();
    
    @Data
    public static class Endpoint {
        private String name;
        private String url;
    }
}

// CustomService.java - 自定义服务
@Slf4j
public class CustomService {
    
    private final CustomServiceProperties properties;
    
    public CustomService(CustomServiceProperties properties) {
        this.properties = properties;
        log.info("CustomService initialized with name: {}", properties.getName());
    }
    
    /**
     * 执行服务调用
     */
    public String execute(String request) {
        log.info("Executing request: {} with timeout: {}ms", 
            request, properties.getTimeout());
        
        // 模拟服务调用
        try {
            Thread.sleep(100); // 模拟处理时间
            return "Response for: " + request;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Service execution interrupted", e);
        }
    }
    
    /**
     * 获取服务信息
     */
    public Map<String, Object> getServiceInfo() {
        Map<String, Object> info = new HashMap<>();
        info.put("name", properties.getName());
        info.put("timeout", properties.getTimeout());
        info.put("retryCount", properties.getRetryCount());
        info.put("endpointCount", properties.getEndpoints().size());
        return info;
    }
    
    /**
     * 健康检查
     */
    public boolean isHealthy() {
        // 实际应用中可以检查服务状态
        return properties.isEnabled();
    }
}

// CustomServiceAutoConfiguration.java - 自动配置类
@AutoConfiguration
@ConditionalOnClass(CustomService.class)
@ConditionalOnProperty(prefix = "custom.service", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(CustomServiceProperties.class)
@Slf4j
public class CustomServiceAutoConfiguration {
    
    /**
     * 自定义服务Bean
     */
    @Bean
    @ConditionalOnMissingBean
    public CustomService customService(CustomServiceProperties properties) {
        log.info("Auto-configuring CustomService with properties: {}", properties);
        return new CustomService(properties);
    }
    
    /**
     * 自定义服务管理器
     */
    @Bean
    @ConditionalOnBean(CustomService.class)
    @ConditionalOnProperty(prefix = "custom.service", name = "manager.enabled", havingValue = "true")
    public CustomServiceManager customServiceManager(CustomService customService) {
        log.info("Auto-configuring CustomServiceManager");
        return new CustomServiceManager(customService);
    }
    
    /**
     * 自定义健康检查指示器
     */
    @Bean
    @ConditionalOnClass(name = "org.springframework.boot.actuator.health.HealthIndicator")
    @ConditionalOnBean(CustomService.class)
    public CustomServiceHealthIndicator customServiceHealthIndicator(CustomService customService) {
        log.info("Auto-configuring CustomServiceHealthIndicator");
        return new CustomServiceHealthIndicator(customService);
    }
}

// CustomServiceManager.java - 服务管理器
@Component
@Slf4j
public class CustomServiceManager {
    
    private final CustomService customService;
    private final AtomicLong requestCount = new AtomicLong(0);
    private final AtomicLong successCount = new AtomicLong(0);
    private final AtomicLong errorCount = new AtomicLong(0);
    
    public CustomServiceManager(CustomService customService) {
        this.customService = customService;
    }
    
    /**
     * 执行带统计的服务调用
     */
    public String executeWithStats(String request) {
        requestCount.incrementAndGet();
        
        try {
            String result = customService.execute(request);
            successCount.incrementAndGet();
            return result;
        } catch (Exception e) {
            errorCount.incrementAndGet();
            log.error("Service execution failed for request: {}", request, e);
            throw e;
        }
    }
    
    /**
     * 获取统计信息
     */
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("requestCount", requestCount.get());
        stats.put("successCount", successCount.get());
        stats.put("errorCount", errorCount.get());
        stats.put("successRate", calculateSuccessRate());
        return stats;
    }
    
    private double calculateSuccessRate() {
        long total = requestCount.get();
        if (total == 0) {
            return 0.0;
        }
        return (double) successCount.get() / total * 100;
    }
}

// CustomServiceHealthIndicator.java - 健康检查指示器
public class CustomServiceHealthIndicator implements HealthIndicator {
    
    private final CustomService customService;
    
    public CustomServiceHealthIndicator(CustomService customService) {
        this.customService = customService;
    }
    
    @Override
    public Health health() {
        try {
            if (customService.isHealthy()) {
                Map<String, Object> serviceInfo = customService.getServiceInfo();
                return Health.up()
                        .withDetails(serviceInfo)
                        .build();
            } else {
                return Health.down()
                        .withDetail("reason", "Service is disabled")
                        .build();
            }
        } catch (Exception e) {
            return Health.down()
                    .withDetail("error", e.getMessage())
                    .build();
        }
    }
}

自动配置架构图示

🎨 自动配置架构图示

                Starter启动器
            →
                Condition条件评估
            →
                BeanBean注册
            →
                Property属性绑定

自动配置流程:Starter触发 → 条件评估 → Bean注册 → 属性绑定

每个环节都有相应的注解和机制支持 条件注解

📍 条件注解

  • @ConditionalOnClass- 类存在时生效
  • @ConditionalOnMissingClass- 类不存在时生效
  • @ConditionalOnBean- Bean存在时生效
  • @ConditionalOnMissingBean- Bean不存在时生效
  • @ConditionalOnProperty- 属性匹配时生效
  • @ConditionalOnResource- 资源存在时生效

配置文件

📄 配置文件

  • spring.factories- 自动配置类声明
  • spring-configuration-metadata.json- 配置元数据
  • additional-spring-configuration-metadata.json- 额外元数据
  • application.yml- 应用配置
  • bootstrap.yml- 引导配置
  • META-INF/spring.factories- 工厂配置

自定义Starter开发

🔧 自定义Starter开发

// 1. 创建spring.factories文件
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.bugstack.springframework.boot.autoconfig.CustomServiceAutoConfiguration

// 2. 创建配置元数据文件
# META-INF/spring-configuration-metadata.json
{
  "groups": [
    {
      "name": "custom.service",
      "type": "cn.bugstack.springframework.boot.autoconfig.CustomServiceProperties",
      "sourceType": "cn.bugstack.springframework.boot.autoconfig.CustomServiceProperties"
    }
  ],
  "properties": [
    {
      "name": "custom.service.enabled",
      "type": "java.lang.Boolean",
      "description": "Whether to enable the custom service.",
      "defaultValue": true
    },
    {
      "name": "custom.service.name",
      "type": "java.lang.String",
      "description": "The name of the custom service.",
      "defaultValue": "Default Service"
    },
    {
      "name": "custom.service.timeout",
      "type": "java.lang.Long",
      "description": "The timeout for service calls in milliseconds.",
      "defaultValue": 30000
    },
    {
      "name": "custom.service.retry-count",
      "type": "java.lang.Integer",
      "description": "The number of retry attempts.",
      "defaultValue": 3
    }
  ]
}

// 3. 创建自定义条件注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnCustomServiceCondition.class)
public @interface ConditionalOnCustomService {
    
    /**
     * 服务名称
     */
    String name() default "";
    
    /**
     * 是否必须启用
     */
    boolean enabled() default true;
}

// OnCustomServiceCondition.java - 自定义条件实现
public class OnCustomServiceCondition implements Condition {
    
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        
        // 获取注解属性
        Map<String, Object> attributes = metadata.getAnnotationAttributes(
                ConditionalOnCustomService.class.getName());
        
        if (attributes == null) {
            return false;
        }
        
        String name = (String) attributes.get("name");
        boolean enabled = (Boolean) attributes.get("enabled");
        
        // 检查服务是否启用
        boolean serviceEnabled = environment.getProperty(
                "custom.service.enabled", Boolean.class, true);
        
        if (!serviceEnabled && enabled) {
            return false;
        }
        
        // 检查特定服务名称
        if (StringUtils.hasText(name)) {
            String serviceName = environment.getProperty("custom.service.name");
            return name.equals(serviceName);
        }
        
        return true;
    }
}

// 4. 使用自定义条件
@Configuration
@ConditionalOnCustomService(name = "special-service", enabled = true)
public class SpecialServiceConfiguration {
    
    @Bean
    public SpecialService specialService() {
        return new SpecialService();
    }
}

// 5. 创建Starter模块的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>cn.bugstack.springframework.boot</groupId>
    <artifactId>custom-service-spring-boot-starter</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <name>Custom Service Spring Boot Starter</name>
    <description>Spring Boot Starter for Custom Service</description>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

// 6. 使用自定义Starter
# 在其他项目的pom.xml中引入
<dependency>
    <groupId>cn.bugstack.springframework.boot</groupId>
    <artifactId>custom-service-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

# 在application.yml中配置
custom:
  service:
    enabled: true
    name: "My Custom Service"
    timeout: 5000
    retry-count: 5

条件注解对比表

📊 条件注解对比

条件注解 作用 使用场景 示例
@ConditionalOnClass 类存在时生效 依赖特定类库 @ConditionalOnClass(DataSource.class)
@ConditionalOnMissingClass 类不存在时生效 提供默认实现 @ConditionalOnMissingClass("com.example.Service")
@ConditionalOnBean Bean存在时生效 依赖其他Bean @ConditionalOnBean(DataSource.class)
@ConditionalOnMissingBean Bean不存在时生效 提供默认Bean @ConditionalOnMissingBean(name = "dataSource")
@ConditionalOnProperty 属性匹配时生效 基于配置启用 @ConditionalOnProperty("app.feature.enabled")
@ConditionalOnResource 资源存在时生效 依赖配置文件 @ConditionalOnResource("classpath:config.xml")

调试和排查

🔍 自动配置调试和排查

// AutoConfigurationController.java - 自动配置调试控制器
@RestController
@RequestMapping("/autoconfig")
@Slf4j
public class AutoConfigurationController {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @Autowired
    private Environment environment;
    
    /**
     * 获取自动配置报告
     */
    @GetMapping("/report")
    public ResponseEntity<Map<String, Object>> getAutoConfigurationReport() {
        Map<String, Object> report = new HashMap<>();
        
        // 获取所有Bean名称
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        report.put("totalBeans", beanNames.length);
        report.put("beanNames", Arrays.asList(beanNames));
        
        // 获取自动配置相关的Bean
        List<String> autoConfigBeans = Arrays.stream(beanNames)
                .filter(name -> name.contains("AutoConfiguration"))
                .collect(Collectors.toList());
        report.put("autoConfigBeans", autoConfigBeans);
        
        return ResponseEntity.ok(report);
    }
    
    /**
     * 获取条件评估报告
     */
    @GetMapping("/conditions")
    public ResponseEntity<Map<String, Object>> getConditionEvaluationReport() {
        Map<String, Object> report = new HashMap<>();
        
        // 这里可以通过ConditionEvaluationReport获取详细信息
        // 实际实现需要访问SpringBoot内部API
        
        report.put("message", "Condition evaluation report");
        report.put("timestamp", System.currentTimeMillis());
        
        return ResponseEntity.ok(report);
    }
    
    /**
     * 获取配置属性
     */
    @GetMapping("/properties")
    public ResponseEntity<Map<String, Object>> getConfigurationProperties() {
        Map<String, Object> properties = new HashMap<>();
        
        // 获取自定义配置属性
        properties.put("custom.service.enabled", 
            environment.getProperty("custom.service.enabled"));
        properties.put("custom.service.name", 
            environment.getProperty("custom.service.name"));
        properties.put("custom.service.timeout", 
            environment.getProperty("custom.service.timeout"));
        
        // 获取所有以custom开头的属性
        Map<String, Object> customProperties = new HashMap<>();
        if (environment instanceof ConfigurableEnvironment) {
            ConfigurableEnvironment configurableEnv = (ConfigurableEnvironment) environment;
            for (PropertySource<?> propertySource : configurableEnv.getPropertySources()) {
                if (propertySource instanceof EnumerablePropertySource) {
                    EnumerablePropertySource<?> enumerablePropertySource = 
                            (EnumerablePropertySource<?>) propertySource;
                    for (String propertyName : enumerablePropertySource.getPropertyNames()) {
                        if (propertyName.startsWith("custom.")) {
                            customProperties.put(propertyName, 
                                environment.getProperty(propertyName));
                        }
                    }
                }
            }
        }
        properties.put("customProperties", customProperties);
        
        return ResponseEntity.ok(properties);
    }
    
    /**
     * 测试自定义服务
     */
    @GetMapping("/test-service")
    public ResponseEntity<Map<String, Object>> testCustomService() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 检查CustomService是否存在
            if (applicationContext.containsBean("customService")) {
                CustomService customService = applicationContext.getBean(CustomService.class);
                
                // 测试服务调用
                String response = customService.execute("test-request");
                Map<String, Object> serviceInfo = customService.getServiceInfo();
                
                result.put("serviceExists", true);
                result.put("response", response);
                result.put("serviceInfo", serviceInfo);
                result.put("healthy", customService.isHealthy());
            } else {
                result.put("serviceExists", false);
                result.put("message", "CustomService bean not found");
            }
        } catch (Exception e) {
            result.put("error", e.getMessage());
            log.error("Error testing custom service", e);
        }
        
        return ResponseEntity.ok(result);
    }
}

# 启用自动配置调试
# application.yml
debug: true

# 或者通过启动参数
# java -jar app.jar --debug

# 查看自动配置报告的方法:
# 1. 启动时添加 --debug 参数
# 2. 查看控制台输出的CONDITIONS EVALUATION REPORT
# 3. 访问 /autoconfig/report 端点
# 4. 使用Spring Boot Actuator的 /actuator/conditions 端点

# 常用调试命令
# 查看所有Bean
curl http://localhost:8080/autoconfig/report

# 查看配置属性
curl http://localhost:8080/autoconfig/properties

# 测试自定义服务
curl http://localhost:8080/autoconfig/test-service

# 查看条件评估(需要Actuator)
curl http://localhost:8080/actuator/conditions

最佳实践

💡 自动配置最佳实践

🎯 开发建议合理使用条件注解- 确保自动配置在正确的条件下生效提供配置属性- 使用@ConfigurationProperties提供可配置选项编写配置元数据- 提供IDE智能提示和文档测试自动配置- 编写单元测试验证配置逻辑文档和示例- 提供清晰的使用文档和示例

# 自动配置开发检查清单

## 1. 配置类设计
- [ ] 使用@AutoConfiguration注解
- [ ] 添加适当的条件注解
- [ ] 提供@ConfigurationProperties类
- [ ] 实现配置的默认值

## 2. 条件设计
- [ ] @ConditionalOnClass检查必要的类
- [ ] @ConditionalOnMissingBean避免重复配置
- [ ] @ConditionalOnProperty提供开关控制
- [ ] 自定义条件注解(如需要)

## 3. 配置文件
- [ ] 创建spring.factories文件
- [ ] 编写配置元数据JSON
- [ ] 提供默认配置示例
- [ ] 文档化所有配置选项

## 4. 测试验证
- [ ] 单元测试自动配置逻辑
- [ ] 集成测试完整流程
- [ ] 测试不同条件下的行为
- [ ] 验证配置属性绑定

## 5. 文档和发布
- [ ] 编写README文档
- [ ] 提供使用示例
- [ ] 版本兼容性说明
- [ ] 发布到Maven仓库

# 示例项目结构
custom-service-spring-boot-starter/
├── src/main/java/
│   └── cn/bugstack/springframework/boot/autoconfig/
│       ├── CustomService.java
│       ├── CustomServiceProperties.java
│       ├── CustomServiceAutoConfiguration.java
│       └── condition/
│           └── OnCustomServiceCondition.java
├── src/main/resources/
│   └── META-INF/
│       ├── spring.factories
│       └── spring-configuration-metadata.json
├── src/test/java/
│   └── cn/bugstack/springframework/boot/autoconfig/
│       └── CustomServiceAutoConfigurationTest.java
├── README.md
└── pom.xml

下一章节

🎉 恭喜完成第12章学习!

你已经掌握了SpringBoot自动配置的核心技能,接下来学习应用部署和Tomcat配置! 🚀 下一章:SpringBoot Tomcat ⬅️ 返回第11章 🏠 返回课程首页

⚙️ SpringBoot AutoConfig
http://www.clxhxhhr.top/posts/2880/
作者
clxstart
发布于
2026-09-19
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。