SpringBoot学习路径二--Spring Boot自动配置原理深度解析

发布于:2025-07-26 ⋅ 阅读:(14) ⋅ 点赞:(0)

        SpringBoot最核心的功能就是自动装配,Starter作为SpringBoot的核心功能之一,基于自动配置代码提供了自动配置模块及依赖的能力,让软件集成变得简单、易用。使用SpringBoot时,我们只需引I人对应的Starter,SpringBoot启动时便会自动加载相关依赖,集成相关功能,这便是SpringBoot的自动装配功能。
简单概括其自动配置的原理:由@SpringBootAppliction组合注解中的@EnableAutoConfiguration注解开启自动配置,加载spring.factories文件中注册的各种默认定义的XxxAutoConfiguration配置类,并且该类可指定@Conditional条件注解,当其@Conditional条件注解生效时,实例化该配置类中定义的Bean,并注入Spring上下文。

一、自动配置核心机制

1. @SpringBootApplication注解

自动配置的入口是@SpringBootApplication注解,它实际上是一个复合注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    // ...
}

其中最关键的是@EnableAutoConfiguration注解。

2. @EnableAutoConfiguration注解

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

这个注解通过@Import导入了AutoConfigurationImportSelector类,这是自动配置的核心实现类。

二、自动配置核心流程

1. AutoConfigurationImportSelector

AutoConfigurationImportSelector实现了DeferredImportSelector接口,它的核心方法是selectImports()

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

关键调用链:

  1. getAutoConfigurationEntry()

  2. getCandidateConfigurations()

  3. loadFactoryNames()

  4. loadSpringFactories()

2. 加载自动配置类

loadSpringFactories()方法中,会从META-INF/spring.factories文件中加载配置:

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    // ...
    Enumeration<URL> urls = (classLoader != null ?
            classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
            ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION);
    // ...
}

FACTORIES_RESOURCE_LOCATION常量的值为"META-INF/spring.factories"

3. spring.factories文件

以spring-boot-autoconfigure模块为例,它的META-INF/spring.factories文件中定义了大量的自动配置类:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
...

三、条件化自动配置

Spring Boot自动配置的核心思想是"条件化配置",通过一系列@Conditional注解实现。

1. 常用条件注解

  • @ConditionalOnClass:类路径下存在指定类时生效

  • @ConditionalOnMissingClass:类路径下不存在指定类时生效

  • @ConditionalOnBean:容器中存在指定Bean时生效

  • @ConditionalOnMissingBean:容器中不存在指定Bean时生效

  • @ConditionalOnProperty:配置文件中存在指定属性时生效

  • @ConditionalOnResource:类路径下存在指定资源时生效

  • @ConditionalOnWebApplication:是Web应用时生效

  • @ConditionalOnNotWebApplication:不是Web应用时生效

2. 条件注解实现原理

@ConditionalOnClass为例,其实现类是OnClassCondition

@Order(Ordered.HIGHEST_PRECEDENCE)
class OnClassCondition extends FilteringSpringBootCondition {
    
    @Override
    protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
            AutoConfigurationMetadata autoConfigurationMetadata) {
        // ...
        ConditionOutcome outcome = getOutcome(metadata);
        // ...
    }
    
    private ConditionOutcome getOutcome(ConditionMetadata metadata) {
        // 检查类是否存在
        ClassLoader classLoader = getClass().getClassLoader();
        String[] onClasses = metadata.getConditionalOnClass();
        for (String onClass : onClasses) {
            if (!ClassUtils.isPresent(onClass, classLoader)) {
                return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class)
                        .didNotFind("required class").items(Style.QUOTE, onClass));
            }
        }
        return null;
    }
}

四、自动配置执行流程

  1. 启动阶段

    • SpringApplication.run()启动应用

    • 调用refreshContext()刷新应用上下文

  2. 配置类解析

    • ConfigurationClassPostProcessor处理所有配置类

    • 解析@SpringBootApplication和@EnableAutoConfiguration

  3. 自动配置类加载

    • AutoConfigurationImportSelector加载spring.factories中的配置类

    • 过滤掉不满足条件的配置类

  4. Bean定义注册

    • 将筛选后的自动配置类注册为Bean定义

    • 后续由Spring容器实例化这些Bean

五、自动配置示例分析

以DataSourceAutoConfiguration为例:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, 
         DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
    
    @Configuration(proxyBeanMethods = false)
    @Conditional(EmbeddedDatabaseCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import(EmbeddedDataSourceConfiguration.class)
    protected static class EmbeddedDatabaseConfiguration {
    }
    
    @Configuration(proxyBeanMethods = false)
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import({ DataSourceConfiguration.Hikari.class, 
             DataSourceConfiguration.Tomcat.class,
             DataSourceConfiguration.Dbcp2.class,
             DataSourceConfiguration.Generic.class,
             DataSourceJmxConfiguration.class })
    protected static class PooledDataSourceConfiguration {
    }
    // ...
}

这个自动配置类展示了典型的条件化配置:

  1. 只有在类路径下存在DataSource和EmbeddedDatabaseType时才生效

  2. 容器中没有ConnectionFactory时才生效

  3. 根据不同的条件导入不同的配置

六、自动配置调试技巧

  1. 查看生效的自动配置
    在application.properties中添加:

    debug=true

    启动时会输出所有自动配置类的评估结果。

  2. 排除特定自动配置

    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
  3. 查看自动配置条件
    通过/actuator/conditions端点(需要actuator依赖)可以查看详细的自动配置条件评估报告。

七、自定义自动配置

  1. 创建META-INF/spring.factories文件

  2. 定义自己的自动配置类

  3. 使用合适的条件注解

@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyServiceProperties.class)
public class MyServiceAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public MyService myService(MyServiceProperties properties) {
        return new MyService(properties);
    }
}

spring.factories中注册:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyServiceAutoConfiguration

八、自动配置的底层原理总结

  1. SPI机制:通过META-INF/spring.factories实现扩展点加载

  2. 条件评估:通过Condition接口实现条件化配置

  3. 延迟加载:通过DeferredImportSelector实现配置类的延迟处理

  4. 配置优先级:通过@AutoConfigureOrder@Order控制配置顺序

Spring Boot的自动配置机制通过这种灵活的条件化方式,既保证了"约定优于配置"的便利性,又提供了足够的灵活性来覆盖默认行为。


网站公告

今日签到

点亮在社区的每一天
去签到