Ruoyi-vue-plus-5.x第五篇Spring框架核心技术:5.1 Spring Boot自动配置

👋 大家好,我是 阿问学长!专注于分享优质开源项目解析、毕业设计项目指导支持、幼小初高教辅资料推荐等,欢迎关注交流!🚀

Spring Boot自动配置

前言

Spring Boot的自动配置是其核心特性之一,通过约定优于配置的理念,大大简化了Spring应用的配置工作。RuoYi-Vue-Plus框架充分利用了Spring Boot的自动配置机制,同时也提供了大量自定义的自动配置类。本文将深入解析Spring Boot自动配置的原理、@Configuration配置类的使用、@ConditionalOn条件注解的应用,以及如何开发自定义Starter等内容。

@Configuration配置类

基础配置类

java 复制代码
/**
 * 系统基础配置类
 */
@Configuration
@EnableConfigurationProperties({SystemProperties.class, SecurityProperties.class})
@ConditionalOnProperty(prefix = "system", name = "enabled", havingValue = "true", matchIfMissing = true)
public class SystemAutoConfiguration {
    
    private static final Logger log = LoggerFactory.getLogger(SystemAutoConfiguration.class);
    
    @Autowired
    private SystemProperties systemProperties;
    
    @Autowired
    private SecurityProperties securityProperties;
    
    /**
     * 系统工具类配置
     */
    @Bean
    @ConditionalOnMissingBean
    public SystemUtils systemUtils() {
        log.info("初始化系统工具类");
        return new SystemUtils(systemProperties);
    }
    
    /**
     * 系统监控配置
     */
    @Bean
    @ConditionalOnProperty(prefix = "system.monitor", name = "enabled", havingValue = "true")
    public SystemMonitor systemMonitor() {
        log.info("初始化系统监控");
        SystemMonitor monitor = new SystemMonitor();
        monitor.setEnabled(systemProperties.getMonitor().isEnabled());
        monitor.setInterval(systemProperties.getMonitor().getInterval());
        return monitor;
    }
    
    /**
     * 系统缓存配置
     */
    @Bean
    @ConditionalOnClass(RedisTemplate.class)
    @ConditionalOnProperty(prefix = "system.cache", name = "type", havingValue = "redis")
    public SystemCacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate) {
        log.info("初始化Redis缓存管理器");
        return new RedisCacheManager(redisTemplate, systemProperties.getCache());
    }
    
    /**
     * 本地缓存配置
     */
    @Bean
    @ConditionalOnMissingBean(SystemCacheManager.class)
    @ConditionalOnProperty(prefix = "system.cache", name = "type", havingValue = "local", matchIfMissing = true)
    public SystemCacheManager localCacheManager() {
        log.info("初始化本地缓存管理器");
        return new LocalCacheManager(systemProperties.getCache());
    }
    
    /**
     * 系统事件发布器
     */
    @Bean
    @ConditionalOnMissingBean
    public SystemEventPublisher systemEventPublisher(ApplicationEventPublisher eventPublisher) {
        log.info("初始化系统事件发布器");
        return new SystemEventPublisher(eventPublisher);
    }
    
    /**
     * 系统任务调度器
     */
    @Bean
    @ConditionalOnProperty(prefix = "system.scheduler", name = "enabled", havingValue = "true")
    @ConditionalOnMissingBean
    public SystemTaskScheduler systemTaskScheduler() {
        log.info("初始化系统任务调度器");
        SystemTaskScheduler scheduler = new SystemTaskScheduler();
        scheduler.setPoolSize(systemProperties.getScheduler().getPoolSize());
        scheduler.setThreadNamePrefix(systemProperties.getScheduler().getThreadNamePrefix());
        return scheduler;
    }
    
    /**
     * 系统配置后处理器
     */
    @PostConstruct
    public void postConstruct() {
        log.info("系统自动配置完成,配置信息:{}", systemProperties);
    }
}

/**
 * 系统属性配置
 */
@Data
@ConfigurationProperties(prefix = "system")
public class SystemProperties {
    
    /**
     * 是否启用系统功能
     */
    private boolean enabled = true;
    
    /**
     * 系统名称
     */
    private String name = "RuoYi-Vue-Plus";
    
    /**
     * 系统版本
     */
    private String version = "1.0.0";
    
    /**
     * 监控配置
     */
    private MonitorConfig monitor = new MonitorConfig();
    
    /**
     * 缓存配置
     */
    private CacheConfig cache = new CacheConfig();
    
    /**
     * 调度器配置
     */
    private SchedulerConfig scheduler = new SchedulerConfig();
    
    @Data
    public static class MonitorConfig {
        private boolean enabled = true;
        private Duration interval = Duration.ofSeconds(30);
        private List<String> metrics = Arrays.asList("cpu", "memory", "disk");
    }
    
    @Data
    public static class CacheConfig {
        private String type = "local";
        private Duration ttl = Duration.ofMinutes(30);
        private int maxSize = 1000;
        private String keyPrefix = "system:";
    }
    
    @Data
    public static class SchedulerConfig {
        private boolean enabled = false;
        private int poolSize = 10;
        private String threadNamePrefix = "system-task-";
    }
}

/**
 * 安全属性配置
 */
@Data
@ConfigurationProperties(prefix = "security")
public class SecurityProperties {
    
    /**
     * 是否启用安全功能
     */
    private boolean enabled = true;
    
    /**
     * 加密配置
     */
    private EncryptionConfig encryption = new EncryptionConfig();
    
    /**
     * 访问控制配置
     */
    private AccessControlConfig accessControl = new AccessControlConfig();
    
    @Data
    public static class EncryptionConfig {
        private String algorithm = "AES";
        private String key = "default-key";
        private String charset = "UTF-8";
    }
    
    @Data
    public static class AccessControlConfig {
        private boolean enableIpFilter = false;
        private List<String> allowedIps = new ArrayList<>();
        private List<String> blockedIps = new ArrayList<>();
    }
}

数据源配置类

java 复制代码
/**
 * 数据源自动配置类
 */
@Configuration
@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
    
    private static final Logger log = LoggerFactory.getLogger(DataSourceAutoConfiguration.class);
    
    /**
     * 主数据源配置
     */
    @Bean
    @Primary
    @ConditionalOnProperty(prefix = "spring.datasource", name = "url")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource primaryDataSource() {
        log.info("初始化主数据源");
        return DataSourceBuilder.create().build();
    }
    
    /**
     * 从数据源配置
     */
    @Bean
    @ConditionalOnProperty(prefix = "spring.datasource.slave", name = "url")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        log.info("初始化从数据源");
        return DataSourceBuilder.create().build();
    }
    
    /**
     * 动态数据源配置
     */
    @Bean
    @ConditionalOnBean(name = {"primaryDataSource", "slaveDataSource"})
    @ConditionalOnProperty(prefix = "dynamic.datasource", name = "enabled", havingValue = "true")
    public DataSource dynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,
                                       @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        log.info("初始化动态数据源");
        
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("primary", primaryDataSource);
        dataSourceMap.put("slave", slaveDataSource);
        
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);
        
        return dynamicDataSource;
    }
    
    /**
     * JdbcTemplate配置
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(DataSource.class)
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        log.info("初始化JdbcTemplate");
        return new JdbcTemplate(dataSource);
    }
    
    /**
     * 事务管理器配置
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(DataSource.class)
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        log.info("初始化事务管理器");
        return new DataSourceTransactionManager(dataSource);
    }
}

/**
 * 动态数据源
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

/**
 * 数据源上下文持有者
 */
public class DataSourceContextHolder {
    
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
    
    public static void setDataSourceType(String dataSourceType) {
        CONTEXT_HOLDER.set(dataSourceType);
    }
    
    public static String getDataSourceType() {
        return CONTEXT_HOLDER.get();
    }
    
    public static void clearDataSourceType() {
        CONTEXT_HOLDER.remove();
    }
}

@ConditionalOn条件注解

常用条件注解

java 复制代码
/**
 * 条件注解示例配置类
 */
@Configuration
public class ConditionalConfiguration {
    
    /**
     * 基于类路径的条件配置
     */
    @Bean
    @ConditionalOnClass(RedisTemplate.class)
    public RedisService redisService() {
        return new RedisService();
    }
    
    /**
     * 基于缺失类的条件配置
     */
    @Bean
    @ConditionalOnMissingClass("org.springframework.data.redis.core.RedisTemplate")
    public LocalCacheService localCacheService() {
        return new LocalCacheService();
    }
    
    /**
     * 基于Bean存在的条件配置
     */
    @Bean
    @ConditionalOnBean(DataSource.class)
    public DatabaseService databaseService(DataSource dataSource) {
        return new DatabaseService(dataSource);
    }
    
    /**
     * 基于Bean缺失的条件配置
     */
    @Bean
    @ConditionalOnMissingBean(CacheManager.class)
    public CacheManager defaultCacheManager() {
        return new ConcurrentMapCacheManager();
    }
    
    /**
     * 基于属性的条件配置
     */
    @Bean
    @ConditionalOnProperty(
        prefix = "feature.email", 
        name = "enabled", 
        havingValue = "true",
        matchIfMissing = false
    )
    public EmailService emailService() {
        return new EmailService();
    }
    
    /**
     * 基于资源的条件配置
     */
    @Bean
    @ConditionalOnResource(resources = "classpath:config/custom.properties")
    public CustomConfigService customConfigService() {
        return new CustomConfigService();
    }
    
    /**
     * 基于Web应用的条件配置
     */
    @Bean
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    public WebMvcConfigurer webMvcConfigurer() {
        return new CustomWebMvcConfigurer();
    }
    
    /**
     * 基于非Web应用的条件配置
     */
    @Bean
    @ConditionalOnNotWebApplication
    public CommandLineRunner commandLineRunner() {
        return args -> System.out.println("非Web应用启动");
    }
    
    /**
     * 基于表达式的条件配置
     */
    @Bean
    @ConditionalOnExpression("${feature.advanced.enabled:false} and ${feature.experimental.enabled:false}")
    public AdvancedFeatureService advancedFeatureService() {
        return new AdvancedFeatureService();
    }
    
    /**
     * 基于Java版本的条件配置
     */
    @Bean
    @ConditionalOnJava(JavaVersion.EIGHT)
    public Java8SpecificService java8SpecificService() {
        return new Java8SpecificService();
    }
}

自定义条件注解

java 复制代码
/**
 * 自定义操作系统条件注解
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnOperatingSystemCondition.class)
public @interface ConditionalOnOperatingSystem {
    
    /**
     * 操作系统类型
     */
    OS value();
    
    enum OS {
        WINDOWS, LINUX, MAC, UNIX
    }
}

/**
 * 操作系统条件实现
 */
public class OnOperatingSystemCondition implements Condition {
    
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> attributes = metadata.getAnnotationAttributes(
            ConditionalOnOperatingSystem.class.getName());
        
        if (attributes == null) {
            return false;
        }
        
        ConditionalOnOperatingSystem.OS requiredOS = 
            (ConditionalOnOperatingSystem.OS) attributes.get("value");
        
        String osName = System.getProperty("os.name").toLowerCase();
        
        switch (requiredOS) {
            case WINDOWS:
                return osName.contains("windows");
            case LINUX:
                return osName.contains("linux");
            case MAC:
                return osName.contains("mac");
            case UNIX:
                return osName.contains("unix");
            default:
                return false;
        }
    }
}

/**
 * 自定义环境条件注解
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnEnvironmentCondition.class)
public @interface ConditionalOnEnvironment {
    
    /**
     * 环境名称
     */
    String[] value();
    
    /**
     * 匹配模式
     */
    MatchMode mode() default MatchMode.ANY;
    
    enum MatchMode {
        ANY, ALL
    }
}

/**
 * 环境条件实现
 */
public class OnEnvironmentCondition implements Condition {
    
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> attributes = metadata.getAnnotationAttributes(
            ConditionalOnEnvironment.class.getName());
        
        if (attributes == null) {
            return false;
        }
        
        String[] requiredEnvs = (String[]) attributes.get("value");
        ConditionalOnEnvironment.MatchMode mode = 
            (ConditionalOnEnvironment.MatchMode) attributes.get("mode");
        
        String[] activeProfiles = context.getEnvironment().getActiveProfiles();
        Set<String> activeProfileSet = new HashSet<>(Arrays.asList(activeProfiles));
        
        if (mode == ConditionalOnEnvironment.MatchMode.ALL) {
            return activeProfileSet.containsAll(Arrays.asList(requiredEnvs));
        } else {
            return Arrays.stream(requiredEnvs)
                .anyMatch(activeProfileSet::contains);
        }
    }
}

/**
 * 使用自定义条件注解的配置类
 */
@Configuration
public class CustomConditionalConfiguration {
    
    /**
     * Windows系统特定配置
     */
    @Bean
    @ConditionalOnOperatingSystem(ConditionalOnOperatingSystem.OS.WINDOWS)
    public WindowsSpecificService windowsSpecificService() {
        return new WindowsSpecificService();
    }
    
    /**
     * Linux系统特定配置
     */
    @Bean
    @ConditionalOnOperatingSystem(ConditionalOnOperatingSystem.OS.LINUX)
    public LinuxSpecificService linuxSpecificService() {
        return new LinuxSpecificService();
    }
    
    /**
     * 开发或测试环境配置
     */
    @Bean
    @ConditionalOnEnvironment(value = {"dev", "test"}, mode = ConditionalOnEnvironment.MatchMode.ANY)
    public DebugService debugService() {
        return new DebugService();
    }
    
    /**
     * 生产环境配置
     */
    @Bean
    @ConditionalOnEnvironment("prod")
    public ProductionService productionService() {
        return new ProductionService();
    }
}

自定义Starter开发

Starter项目结构

复制代码
ruoyi-spring-boot-starter/
├── src/
│   └── main/
│       ├── java/
│       │   └── com/ruoyi/starter/
│       │       ├── autoconfigure/
│       │       │   ├── RuoyiAutoConfiguration.java
│       │       │   ├── RuoyiProperties.java
│       │       │   └── condition/
│       │       ├── service/
│       │       │   ├── RuoyiService.java
│       │       │   └── impl/
│       │       └── util/
│       └── resources/
│           └── META-INF/
│               ├── spring.factories
│               └── spring-configuration-metadata.json
└── pom.xml

Starter核心实现

java 复制代码
/**
 * RuoYi自动配置类
 */
@Configuration
@EnableConfigurationProperties(RuoyiProperties.class)
@ConditionalOnProperty(prefix = "ruoyi", name = "enabled", havingValue = "true", matchIfMissing = true)
@AutoConfigureAfter({DataSourceAutoConfiguration.class, RedisAutoConfiguration.class})
public class RuoyiAutoConfiguration {
    
    private static final Logger log = LoggerFactory.getLogger(RuoyiAutoConfiguration.class);
    
    @Autowired
    private RuoyiProperties ruoyiProperties;
    
    /**
     * RuoYi核心服务
     */
    @Bean
    @ConditionalOnMissingBean
    public RuoyiService ruoyiService() {
        log.info("初始化RuoYi核心服务,配置:{}", ruoyiProperties);
        return new RuoyiServiceImpl(ruoyiProperties);
    }
    
    /**
     * RuoYi工具类
     */
    @Bean
    @ConditionalOnMissingBean
    public RuoyiUtils ruoyiUtils() {
        log.info("初始化RuoYi工具类");
        return new RuoyiUtils(ruoyiProperties);
    }
    
    /**
     * RuoYi缓存管理器
     */
    @Bean
    @ConditionalOnClass(RedisTemplate.class)
    @ConditionalOnProperty(prefix = "ruoyi.cache", name = "enabled", havingValue = "true")
    public RuoyiCacheManager ruoyiCacheManager(RedisTemplate<String, Object> redisTemplate) {
        log.info("初始化RuoYi缓存管理器");
        return new RuoyiCacheManager(redisTemplate, ruoyiProperties.getCache());
    }
    
    /**
     * RuoYi事件监听器
     */
    @Bean
    @ConditionalOnProperty(prefix = "ruoyi.event", name = "enabled", havingValue = "true")
    public RuoyiEventListener ruoyiEventListener() {
        log.info("初始化RuoYi事件监听器");
        return new RuoyiEventListener(ruoyiProperties.getEvent());
    }
    
    /**
     * RuoYi Web配置
     */
    @Configuration
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    @ConditionalOnProperty(prefix = "ruoyi.web", name = "enabled", havingValue = "true")
    static class RuoyiWebConfiguration {
        
        @Bean
        public RuoyiWebMvcConfigurer ruoyiWebMvcConfigurer(RuoyiProperties ruoyiProperties) {
            log.info("初始化RuoYi Web配置");
            return new RuoyiWebMvcConfigurer(ruoyiProperties.getWeb());
        }
        
        @Bean
        public RuoyiInterceptor ruoyiInterceptor(RuoyiProperties ruoyiProperties) {
            log.info("初始化RuoYi拦截器");
            return new RuoyiInterceptor(ruoyiProperties.getWeb());
        }
    }
    
    /**
     * RuoYi数据库配置
     */
    @Configuration
    @ConditionalOnClass(DataSource.class)
    @ConditionalOnProperty(prefix = "ruoyi.database", name = "enabled", havingValue = "true")
    static class RuoyiDatabaseConfiguration {
        
        @Bean
        public RuoyiDatabaseInitializer ruoyiDatabaseInitializer(DataSource dataSource, 
                                                                RuoyiProperties ruoyiProperties) {
            log.info("初始化RuoYi数据库初始化器");
            return new RuoyiDatabaseInitializer(dataSource, ruoyiProperties.getDatabase());
        }
        
        @Bean
        public RuoyiDataSourceHealthIndicator ruoyiDataSourceHealthIndicator(DataSource dataSource) {
            log.info("初始化RuoYi数据源健康检查");
            return new RuoyiDataSourceHealthIndicator(dataSource);
        }
    }
}

/**
 * RuoYi属性配置
 */
@Data
@ConfigurationProperties(prefix = "ruoyi")
public class RuoyiProperties {
    
    /**
     * 是否启用RuoYi功能
     */
    private boolean enabled = true;
    
    /**
     * 应用名称
     */
    private String appName = "RuoYi Application";
    
    /**
     * 应用版本
     */
    private String version = "1.0.0";
    
    /**
     * 缓存配置
     */
    private CacheProperties cache = new CacheProperties();
    
    /**
     * 事件配置
     */
    private EventProperties event = new EventProperties();
    
    /**
     * Web配置
     */
    private WebProperties web = new WebProperties();
    
    /**
     * 数据库配置
     */
    private DatabaseProperties database = new DatabaseProperties();
    
    @Data
    public static class CacheProperties {
        private boolean enabled = true;
        private String prefix = "ruoyi:";
        private Duration ttl = Duration.ofMinutes(30);
        private int maxSize = 1000;
    }
    
    @Data
    public static class EventProperties {
        private boolean enabled = true;
        private boolean async = true;
        private int threadPoolSize = 10;
    }
    
    @Data
    public static class WebProperties {
        private boolean enabled = true;
        private String contextPath = "/";
        private List<String> allowedOrigins = Arrays.asList("*");
        private boolean enableCors = true;
    }
    
    @Data
    public static class DatabaseProperties {
        private boolean enabled = true;
        private boolean autoInit = false;
        private String initScript = "classpath:sql/init.sql";
        private boolean showSql = false;
    }
}

spring.factories配置

properties 复制代码
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.starter.autoconfigure.RuoyiAutoConfiguration

# Application Listeners
org.springframework.context.ApplicationListener=\
com.ruoyi.starter.listener.RuoyiApplicationListener

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
com.ruoyi.starter.env.RuoyiEnvironmentPostProcessor

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.ruoyi.starter.diagnostics.RuoyiFailureAnalyzer

配置元数据

json 复制代码
{
  "groups": [
    {
      "name": "ruoyi",
      "type": "com.ruoyi.starter.autoconfigure.RuoyiProperties",
      "sourceType": "com.ruoyi.starter.autoconfigure.RuoyiProperties"
    }
  ],
  "properties": [
    {
      "name": "ruoyi.enabled",
      "type": "java.lang.Boolean",
      "description": "是否启用RuoYi功能",
      "defaultValue": true
    },
    {
      "name": "ruoyi.app-name",
      "type": "java.lang.String",
      "description": "应用名称",
      "defaultValue": "RuoYi Application"
    },
    {
      "name": "ruoyi.version",
      "type": "java.lang.String",
      "description": "应用版本",
      "defaultValue": "1.0.0"
    },
    {
      "name": "ruoyi.cache.enabled",
      "type": "java.lang.Boolean",
      "description": "是否启用缓存功能",
      "defaultValue": true
    },
    {
      "name": "ruoyi.cache.prefix",
      "type": "java.lang.String",
      "description": "缓存键前缀",
      "defaultValue": "ruoyi:"
    },
    {
      "name": "ruoyi.cache.ttl",
      "type": "java.time.Duration",
      "description": "缓存过期时间",
      "defaultValue": "30m"
    },
    {
      "name": "ruoyi.event.enabled",
      "type": "java.lang.Boolean",
      "description": "是否启用事件功能",
      "defaultValue": true
    },
    {
      "name": "ruoyi.event.async",
      "type": "java.lang.Boolean",
      "description": "是否异步处理事件",
      "defaultValue": true
    },
    {
      "name": "ruoyi.web.enabled",
      "type": "java.lang.Boolean",
      "description": "是否启用Web功能",
      "defaultValue": true
    },
    {
      "name": "ruoyi.web.enable-cors",
      "type": "java.lang.Boolean",
      "description": "是否启用跨域支持",
      "defaultValue": true
    }
  ],
  "hints": [
    {
      "name": "ruoyi.cache.ttl",
      "values": [
        {
          "value": "30m",
          "description": "30分钟"
        },
        {
          "value": "1h",
          "description": "1小时"
        },
        {
          "value": "1d",
          "description": "1天"
        }
      ]
    }
  ]
}

配置属性绑定

属性绑定示例

java 复制代码
/**
 * 应用配置属性
 */
@Data
@Component
@ConfigurationProperties(prefix = "app")
@Validated
public class ApplicationProperties {
    
    /**
     * 应用基本信息
     */
    @NotBlank(message = "应用名称不能为空")
    private String name;
    
    @NotBlank(message = "应用版本不能为空")
    private String version;
    
    @Email(message = "邮箱格式不正确")
    private String contactEmail;
    
    /**
     * 功能开关
     */
    private FeatureFlags features = new FeatureFlags();
    
    /**
     * 第三方服务配置
     */
    private Map<String, ThirdPartyService> services = new HashMap<>();
    
    /**
     * 环境相关配置
     */
    private EnvironmentConfig environment = new EnvironmentConfig();
    
    @Data
    public static class FeatureFlags {
        private boolean enableCache = true;
        private boolean enableMonitoring = true;
        private boolean enableSecurity = true;
        private boolean enableAudit = false;
    }
    
    @Data
    @Validated
    public static class ThirdPartyService {
        @NotBlank
        private String url;
        
        @Min(1000)
        @Max(30000)
        private int timeout = 5000;
        
        @Min(1)
        @Max(10)
        private int retryCount = 3;
        
        private Map<String, String> headers = new HashMap<>();
    }
    
    @Data
    public static class EnvironmentConfig {
        private String profile;
        private String region = "default";
        private boolean debug = false;
        private LogLevel logLevel = LogLevel.INFO;
    }
    
    public enum LogLevel {
        TRACE, DEBUG, INFO, WARN, ERROR
    }
}

/**
 * 配置属性使用示例
 */
@Service
public class ApplicationService {
    
    @Autowired
    private ApplicationProperties applicationProperties;
    
    public void printApplicationInfo() {
        System.out.println("应用名称: " + applicationProperties.getName());
        System.out.println("应用版本: " + applicationProperties.getVersion());
        System.out.println("联系邮箱: " + applicationProperties.getContactEmail());
        
        FeatureFlags features = applicationProperties.getFeatures();
        System.out.println("缓存功能: " + (features.isEnableCache() ? "启用" : "禁用"));
        System.out.println("监控功能: " + (features.isEnableMonitoring() ? "启用" : "禁用"));
        
        Map<String, ThirdPartyService> services = applicationProperties.getServices();
        services.forEach((name, service) -> {
            System.out.println("服务 " + name + ": " + service.getUrl() + 
                             ", 超时: " + service.getTimeout() + "ms");
        });
    }
}

配置文件示例

yaml 复制代码
# application.yml
app:
  name: "RuoYi管理系统"
  version: "2.0.0"
  contact-email: "admin@ruoyi.vip"
  
  features:
    enable-cache: true
    enable-monitoring: true
    enable-security: true
    enable-audit: false
  
  services:
    payment:
      url: "https://api.payment.com"
      timeout: 10000
      retry-count: 3
      headers:
        Authorization: "Bearer token"
        Content-Type: "application/json"
    
    notification:
      url: "https://api.notification.com"
      timeout: 5000
      retry-count: 2
  
  environment:
    profile: "production"
    region: "cn-north-1"
    debug: false
    log-level: INFO

# 系统配置
system:
  enabled: true
  name: "RuoYi-Vue-Plus"
  version: "1.0.0"
  
  monitor:
    enabled: true
    interval: 30s
    metrics:
      - cpu
      - memory
      - disk
  
  cache:
    type: redis
    ttl: 30m
    max-size: 1000
    key-prefix: "system:"
  
  scheduler:
    enabled: true
    pool-size: 10
    thread-name-prefix: "system-task-"

# 安全配置
security:
  enabled: true
  
  encryption:
    algorithm: AES
    key: "my-secret-key-123456"
    charset: UTF-8
  
  access-control:
    enable-ip-filter: true
    allowed-ips:
      - "192.168.1.0/24"
      - "10.0.0.0/8"
    blocked-ips:
      - "192.168.1.100"

总结

本文详细介绍了Spring Boot自动配置的核心技术,包括:

  1. @Configuration配置类:系统配置类、数据源配置类的实现
  2. @ConditionalOn条件注解:常用条件注解、自定义条件注解的开发
  3. 自定义Starter开发:完整的Starter项目结构和实现
  4. 配置属性绑定:@ConfigurationProperties的使用和验证

这些技术是Spring Boot应用开发的基础,掌握这些内容有助于更好地理解和使用Spring Boot框架。

在下一篇文章中,我们将探讨Spring Security集成。

参考资料

相关推荐
给月亮点灯|3 小时前
Vue基础知识-脚手架开发-使用Axios发送异步请求+代理服务器解决前后端分离项目的跨域问题
前端·javascript·vue.js
晚安里3 小时前
Spring 框架(IoC、AOP、Spring Boot) 的必会知识点汇总
java·spring boot·spring
上官浩仁4 小时前
springboot ioc 控制反转入门与实战
java·spring boot·spring
deepwater_zone4 小时前
Spring 微服务
spring·微服务
叫我阿柒啊4 小时前
从Java全栈到前端框架:一位程序员的实战之路
java·spring boot·微服务·消息队列·vue3·前端开发·后端开发
中国胖子风清扬5 小时前
Rust 序列化技术全解析:从基础到实战
开发语言·c++·spring boot·vscode·后端·中间件·rust
quan26316 小时前
Vue实践篇-02,AI生成代码
前端·javascript·vue.js
qb7 小时前
vue3.5.18源码-编译-入口
前端·vue.js·架构
虫无涯7 小时前
【分享】基于百度脑图,并使用Vue二次开发的用例脑图编辑器组件
前端·vue.js·编辑器