做网站需要的课程,0基础网站建设教程视频教程,公司建网站带商城可以吗,中国电信网站备案流程文章目录问题SpringBootApplication注解AutoConfigurationPackages.Registrar类AutoConfigurationImportSelector类springboot如何加载其他的starter总结问题
为什么我们在使用springboot的时候#xff0c;只需要在maven中导入starter就能够使用呢#xff1f;这里来分析一下…
文章目录问题SpringBootApplication注解AutoConfigurationPackages.Registrar类AutoConfigurationImportSelector类springboot如何加载其他的starter总结问题
为什么我们在使用springboot的时候只需要在maven中导入starter就能够使用呢这里来分析一下
SpringBootApplication注解
这个注解一般用在springboot程序的主启动类上这个注解除去元注解由下面几个注解构成
SpringBootConfiguration
EnableAutoConfiguration
ComponentScan(excludeFilters { Filter(type FilterType.CUSTOM, classes TypeExcludeFilter.class),Filter(type FilterType.CUSTOM, classes AutoConfigurationExcludeFilter.class) })SpringBootConfiguration是由下面两个注解构成
Configuration
IndexedEnableAutoConfiguration是由下面内容构成
AutoConfigurationPackage
Import(AutoConfigurationImportSelector.class)AutoConfigurationPackage内容如下
Import(AutoConfigurationPackages.Registrar.class)所以SpringBootApplication等价于下面内容
// SpringBootConfiguration
Configuration
Indexed// EnableAutoConfiguration
Import(AutoConfigurationPackages.Registrar.class)
Import(AutoConfigurationImportSelector.class)ComponentScan(excludeFilters { Filter(type FilterType.CUSTOM, classes TypeExcludeFilter.class),Filter(type FilterType.CUSTOM, classes AutoConfigurationExcludeFilter.class) })可以发现实际就是导入了两个类一个AutoConfigurationPackages.Registrar一个AutoConfigurationImportSelector。 AutoConfigurationPackages.Registrar类
这个类的信息如下 /*** {link ImportBeanDefinitionRegistrar} to store the base package from the importing* configuration.*/static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));}Overridepublic SetObject determineImports(AnnotationMetadata metadata) {return Collections.singleton(new PackageImports(metadata));}}作用就是获取要扫描的包路径 AutoConfigurationImportSelector类
这个类的内容如下 里面实现了多个接口以Aware结尾的接口其实就是完成某种资源的设置Ordered就是用于指定bean加载顺序的最重要的是DeferredImportSelector这个接口继承了ImportSelectorImportSelector就可以完成bean的注入工作 这个接口里面的group类里面就包含了要进行加载的bean信息 回到实现类也就是AutoConfigurationImportSelector去到process方法
Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,() - String.format(Only %s implementations are supported, got %s,AutoConfigurationImportSelector.class.getSimpleName(),deferredImportSelector.getClass().getName()));AutoConfigurationEntry autoConfigurationEntry ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);this.autoConfigurationEntries.add(autoConfigurationEntry);for (String importClassName : autoConfigurationEntry.getConfigurations()) {this.entries.putIfAbsent(importClassName, annotationMetadata);}
}将这个方法分解一下 // 获取自动配置的类AutoConfigurationEntry autoConfigurationEntry ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);this.autoConfigurationEntries.add(autoConfigurationEntry);// 遍历自动配置的beanfor (String importClassName : autoConfigurationEntry.getConfigurations()) {// 如果存在这个类就进行加入this.entries.putIfAbsent(importClassName, annotationMetadata);}里面关键的就是获取所有的自动配置类关键方法就是getAutoConfigurationEntry这个方法进入这个方法 /*** Return the {link AutoConfigurationEntry} based on the {link AnnotationMetadata}* of the importing {link Configuration Configuration} class.* param annotationMetadata the annotation metadata of the configuration class* return the auto-configurations that should be imported*/protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes getAttributes(annotationMetadata);ListString configurations getCandidateConfigurations(annotationMetadata, attributes);configurations removeDuplicates(configurations);SetString exclusions getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}里面的关键语句就是
ListString configurations getCandidateConfigurations(annotationMetadata, attributes);功能就是完成获取所有要进行自动加载的bean进入到方法 /*** Return the auto-configuration class names that should be considered. By default* this method will load candidates using {link ImportCandidates} with* {link #getSpringFactoriesLoaderFactoryClass()}. For backward compatible reasons it* will also consider {link SpringFactoriesLoader} with* {link #getSpringFactoriesLoaderFactoryClass()}.* param metadata the source metadata* param attributes the {link #getAttributes(AnnotationMetadata) annotation* attributes}* return a list of candidate configurations*/protected ListString getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {ListString configurations new ArrayList(SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);Assert.notEmpty(configurations,No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.);return configurations;}这个方法里面的
ListString configurations new ArrayList(SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));这个方法用于读取类路径下的所有 META-INF/spring.factories文件
下面的这行代码
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);将其拆解为
ImportCandidates ic ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader());ic.forEach(configurations::add);可以发现就是先去获取所有自动加载bean然后将其加入到一个集合中进入到load方法 /*** Loads the names of import candidates from the classpath.** The names of the import candidates are stored in files named* {code META-INF/spring/full-qualified-annotation-name.imports} on the classpath.* Every line contains the full qualified name of the candidate class. Comments are* supported using the # character.* param annotation annotation to load* param classLoader class loader to use for loading* return list of names of annotated classes*/public static ImportCandidates load(Class? annotation, ClassLoader classLoader) {Assert.notNull(annotation, annotation must not be null);ClassLoader classLoaderToUse decideClassloader(classLoader);String location String.format(LOCATION, annotation.getName());EnumerationURL urls findUrlsInClasspath(classLoaderToUse, location);ListString importCandidates new ArrayList();while (urls.hasMoreElements()) {URL url urls.nextElement();importCandidates.addAll(readCandidateConfigurations(url));}return new ImportCandidates(importCandidates);}里面最重要的语句就是
importCandidates.addAll(readCandidateConfigurations(url));其实就是读取配置文件的信息然后加入到集合中。读取的位置就是 META-INF/spring/%s.imports实际上就是去读取 里面一共有144个默认加载项然后再经过一些过滤操作就会返回所有的配置类信息 /*** Return the {link AutoConfigurationEntry} based on the {link AnnotationMetadata}* of the importing {link Configuration Configuration} class.* param annotationMetadata the annotation metadata of the configuration class* return the auto-configurations that should be imported*/protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes getAttributes(annotationMetadata);ListString configurations getCandidateConfigurations(annotationMetadata, attributes);configurations removeDuplicates(configurations);SetString exclusions getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}后面springboot就会去处理这些这些配置类。 springboot如何加载其他的starter
其实上面已经说了springboot会去读取类路径下的所有META-INF/spring.factories文件所以只需要在这个文件中写上自动配置的类即可以mybatis-plus为例子如下 总结
springboot在启动的时候会去读取org\springframework\boot\spring-boot-autoconfigure\2.7.10\spring-boot-autoconfigure-2.7.10.jar!\META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports这个文件中的所有配置。
springboot通过读取META-INF\spring.factories下的配置文件来支持其他starter的注入