首先看一下Springboot的启动流程:
自动配置的关键注解是:@ComponentScan 和 @Import 注解,这两个注解的作用如下:
针对@Import给出实例
public class ConfigA {
@Bean
public A a(){
return new A();
}
}
public class A {
}
// 使用配置类ConfigB将ConfigA的配置导入
@Configuration
@Import(ConfigA.class) // 导入ConfigA的配置
public class ConfigB {
}
接口ImportSelector中有一个selectimports方法,它的返回值是一个字符串数组,数组中的每个元素分别代表一个将被导入的配置类的全限定名;利用此特性我们可以给IOC容器动态地导入多个配置类。
public class ZooConfig {
@Bean
public Tiger tiger() {
return new Tiger();
}
}
public class Tiger {
}
public class ZooImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
return new String[]{"com.xxx.config.ZooConfig"};
}
}
@Configuration
@Import({ZooImportSelector.class})
public class ConfigSelector{
}
通过@Import导入一个ImportBeanDefinitionRegistrar接口的实现类;通过它,可以手动将多个BeanDefinition注册到IOC容器,从而实现个性化定制;利用此特性我们可以给IOC容器动态地导入多个BeanDefinition。
public class Dog{
}
public class ZooRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {
GenericBeanDefinition bd = new GanericBeanDefinition();
bd.setBeanClass(Dog.class);
registry.registerBeanDefinition("dog", bd);
}
}
@Configuration
@Import({ZooRegistrar.class})
public class Config(){
}
首先启动类的@SpringBootApplication注解实现了应用的启动和配置的加载。
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@MapperScan("com.xlt.mapper")
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
@SpringBootApplication注解主要引入了三个注解@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan,作用分别是:
@SpringBootConfiguration:加载 @Configuration注解的配置
@EnableAutoConfiguration:加载自动配置的包和通过@Import注解导入AutoConfigurationImportSelector.class
@ComponentScan:组件扫描
@SpringBootConfiguration // 加载Springboot配置
@EnableAutoConfiguration // 启动加载配置
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) // 组件扫描
public @interface SpringBootApplication {
// ....
}
这里着重看一下@EnableAutoConfiguration注解,
@AutoConfigurationPackage // 注册自动配置的包
@Import(AutoConfigurationImportSelector.class) // 通过SPI机制自动导入配置
public @interface EnableAutoConfiguration {
// ....
}
AutoConfigurationImportSelector类是实现自动配置的核心,它主要是使用使用了SpringFactories机制实现自动配置,SpringFactories的核心逻辑是从classpath中读取到所有jar包中的配置文件META-IF/spring.factories,然后根据指定的key从配置文件中解析出对应的value值,加载的逻辑如下图:
源码实现如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 获取自动配置
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
// 返回配置类的全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 获取属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 获取META-INF/spring.factories中的配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 去重
configurations = removeDuplicates(configurations);
// 去掉排除的配置
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
// 触发自动配置导入相关的事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader
.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),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;
}
}
以mybatis-plus的自动配置加载为例,首先引入依赖
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.1version>
dependency>
在该jar包中的META-IF/spring.factories中,自动配置的信息如下
# Auto Configure
org.springframework.boot.env.EnvironmentPostProcessor=\
com.baomidou.mybatisplus.autoconfigure.SafetyEncryptProcessor
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration
SpringBoot启动时会自动加载这些配置