亲宝软件园·资讯

展开

springboot的自动配置

pavi 人气:0
#### 1. 起因 ​ 使用springboot也有些时间,一直很好奇它如何做到自动配置的,所以查阅了相关资料并且学习了相关内容,才写了这篇文章。 #### 2. 分析 ​ ①第一步我们从它的启动配置类(XxxApplication)收起,我们进入到他的@SpringBootApplication注解。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200307212354659.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bhdmljbg==,size_16,color_FFFFFF,t_70) ​ ②我们可以看到如下代码,由于我们需要找到导致它自动配置的,所以锁定了@EnableAutoConfiguration注解,那么就可以进入这个注解。 ```java @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { @AliasFor( annotation = EnableAutoConfiguration.class ) Class<?>[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class ) String[] excludeName() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackages" ) String[] scanBasePackages() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackageClasses" ) Class<?>[] scanBasePackageClasses() default {}; } ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200307212426892.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bhdmljbg==,size_16,color_FFFFFF,t_70) ​ ③ 我们看到了如下代码,由于这是一个接口,而它的实现类我们又不好确定,所以我们只好从注解入手,由于@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited等都是元注解,我们可以从@AutoConfigurationPackage,@Import({AutoConfigurationImportSelector.class})中找到我们想要的,根据它的中文意思我们可以从@Import({AutoConfigurationImportSelector.class})(自动有选择的导入配置)出发,毕竟不是所有的配置都会都如,而导入那些配置根据项目中使用了那些starter决定。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200307212456502.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bhdmljbg==,size_16,color_FFFFFF,t_70) ​ ④点入第三步提到的注解,进入这个类根据方法名我们可以猜测是和这个方法相关,通过阅读这个代码,我们可以猜测是和getAutoConfigurationEntry这个方法有关,所以不妨点进去。 ```java public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } } ``` ​ ⑤由于我们需要的配置Config,所以大致可以断定是和这个代码有关联**List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);**,所以不妨进到这个getCandidateConfigurations方法中去。 ```java protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); } } ``` ​ ⑥经过第五步,我们可以看到如下代码 ```java protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List 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; } ``` 不妨看这部分代码,**List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());**,它的意思是一个加载器通过加载某个工厂获得配置的List,因此我们在进入到这个的实现是没有必要的,可以从参数考虑,所以锁定在第一个参数,点进入可以看到如下代码。 ```java protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; } ``` 看到这里可能还是会疑惑?为啥就自动配置了,其实我们这个方法(loadFactoryNames)是从一个配置文件中读取内容,它的键是EnableAutoConfiguration,而这个配置文件是在如图所示的文件中。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200307212607881.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200307212651946.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bhdmljbg==,size_16,color_FFFFFF,t_70) ​ ⑥打开上述文件,根据上一步的键找它的值,如图就是springboot配置类,那么项目启动时是不是所有的配置都起作用吗?不妨进入到某个配置类查看即可。如图所示的@ConditionalOnMissingBean注解表示项目的容器是否有这个bean,如果没有这个配置类就不会其作用,另外我们只要在仔细看这个类首先进行了初始化,之后它会从配置文件(application.xml或者application.yml)中获取值。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200307212723198.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bhdmljbg==,size_16,color_FFFFFF,t_70) `注:如有错误,欢迎指出。`

加载全部内容

相关教程
猜你喜欢
用户评论