最近学习springboot的过程中,学到了自动配置的原理,在这里写一下笔记,加深一下印象,方便以后复习。
1.创建一个springboot项目(省略)
2.分析主配置类
@SpringBootApplication // 表示该类是一个主配置类,应该运行该类的main()来启动springboot应用(主入口)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication
注解
@Target(ElementType.TYPE) //表示该注解可以使用的范围,ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention(RetentionPolicy.RUNTIME) // 保存注解信息,RetentionPoicy.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
注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage // 自动配置包
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// 省略方法
}
@AutoConfigurationPackage
注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
@Import(AutoConfigurationPackages.Registrar.class)
注解中的AutoConfigurationPackages.Registrar.class
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
// 扫描主配置类所在的包及其子包。这就是为什么不需要配置@ComponentScan来扫描包。springboot搞定了
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
}
@Import(AutoConfigurationImportSelector.class)
注解
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();
private static final String[] NO_IMPORTS = {};
private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);
private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
private ConfigurableListableBeanFactory beanFactory;
private Environment environment;
private ClassLoader beanClassLoader;
private ResourceLoader resourceLoader;
private ConfigurationClassFilter configurationClassFilter;
@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);
// 获取候选的配置
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) {
/*
1.扫描所有jar包类路径下的 META-INF/spring.factories 文件,这一步,获取到了所有的自动配置类的全限定类名,然后将这些内容包装成了 Properties 类。
2.通过 Properties 类获取到 EnableAutoConfiguration.class类(全限定类名)对应的值,一个一个添加到容器中
*/
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;
}
// 其他方法省略
}
springboot使用的自动配置都是以 xxxAutoConfiguration.class 命名,将每一个的自动配置类都加载到容器中,进行自动配置。
如果需要对某个功能自定义属性,就需要找到 xxxProperties.class ,该类中的每一个属性都是可以通过 @ConfigurationProperties(prefix = “xxx”) 中的 perfile 指定的 前缀+属性 来自定义属性。
本文章是博主学习SpringBoot过程中的一些视频笔记,如有错误,请大佬指出,感谢大佬!