概述
Springboot启动流程
首先看一下Springboot的启动流程:
配置类加载
@ComponentScan和**@Import**注解
自动配置的关键注解是:@ComponentScan 和 @Import 注解,这两个注解的作用如下:
- @ComponentScan
- 对指定的package进行扫描,找到符合条件的类,默认搜索被@Component修饰的配置类
- 通过属性basePackages或basePackageClasses来指定要进行扫描的package;如果没有指定package,则默认扫描当前@ComponentScan所修饰的类所在的package
- @Import
- 提供了一种显式地从其他地方加载配置类的方式,可以避免使用性能较差的组件扫描(@ComponentScan)
- 支持三种导入方式
- 普通类
- 接口ImportSelector的实现类
- 接口ImportBeanDefinitionRegistrar的实现类
针对@Import给出实例
1、导入普通类
public class ConfigA {
@Bean
public A a(){
return new A();
}
}
public class A {
}
// 使用配置类ConfigB将ConfigA的配置导入
@Configuration
@Import(ConfigA.class) // 导入ConfigA的配置
public class ConfigB {
}
2、@Import导入接口ImportSelector的实现类
接口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{
}
3、@Import导入接口ImportBeanDefinitionRegistrar的实现类
通过@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(){
}
Springboot的配置加载过程
首先启动类的@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的自动配置加载为例,首先引入依赖
<!-- mybatis-plus依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</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启动时会自动加载这些配置
最后
以上就是单薄黄豆为你收集整理的SpringBoot配置自动加载机制的全部内容,希望文章能够帮你解决SpringBoot配置自动加载机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复