SpringBoot使用笔记(三)

自动配置

自动配置主要由 @EnableAutoConfiguration 实现,而 @SpringBootApplication 内复合了这个注解,因此被 @SpringBootApplication 的应用程序类就可以实现自动配置。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

可以看到这个注解 import 了 AutoConfigurationImportSelector 类,这个类中的 selectImports() 方法会通过调用 getAutoConfigurationEntry() 方法加载自动配置的配置项。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if (!this.isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    } else {
    	// 加载自动配置的配置项
        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
}

getAutoConfigurationEntry() 方法会调用 getCandidateConfigurations() 方法,而 getCandidateConfigurations() 方法会通过 SpringFactoriesLoader 来加载配置,传入 EnableAutoConfiguration 的类。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    return EnableAutoConfiguration.class;
}

Spring Boot 提供的自动配置类位于 spring-boot-autoconfigure 包下的 spring.factories 文件中,截取部分如下,可以看到 Spring Boot 内置了很多自动配置的类。

# 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,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\

我们以 DataSourceAutoConfiguration 类为例,这个类会自动配置 H2 数据源,具体看下面代码中的解析。

@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 {
    public DataSourceAutoConfiguration() {
    }

	// 重点解读一下这个Configuration, 它的具体功能是配置一个H2数据源
    @Configuration(
        proxyBeanMethods = false
    )
    // 带上 EmbeddedDatabaseCondition 类内定义的条件,满足条件时生效
    @Conditional({DataSourceAutoConfiguration.EmbeddedDatabaseCondition.class})
    // 容器内没有 DataSource 类型或者 XADataSource 类型的 bean 时才生效
    @ConditionalOnMissingBean({DataSource.class, XADataSource.class})
    // 导入 EmbeddedDataSourceConfiguration 类
    @Import({EmbeddedDataSourceConfiguration.class})
    protected static class EmbeddedDatabaseConfiguration {
        protected EmbeddedDatabaseConfiguration() {
        }
    }
}

而 EmbeddedDataSourceConfiguration 这个内嵌数据库的配置则会创建一个类型为 EmbeddedDatabase 的 Bean。

@Configuration(
    proxyBeanMethods = false
)
@EnableConfigurationProperties({DataSourceProperties.class})
public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {
    private ClassLoader classLoader;

    public EmbeddedDataSourceConfiguration() {
    }

    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

	// 创建一个类型为 EmbeddedDatabase 的 Bean
    @Bean(
        destroyMethod = "shutdown"
    )
    public EmbeddedDatabase dataSource(DataSourceProperties properties) {
        return (new EmbeddedDatabaseBuilder()).setType(EmbeddedDatabaseConnection.get(this.classLoader).getType()).setName(properties.determineDatabaseName()).build();
    }
}

至此,整个H2数据源的Bean的创建过程结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值