SpringBoot(三)SpringBoot自动配置
吴锦涛096 人气:2我们都知道SpringBoot帮助我们集成了许多组件和配置,那么SpringBoot是如何集成这些配置并在启动是自动进行配置呢。说到这就不得又需要回过头来看一下@SpringBootApplication这个注解了,之前已经说过这个注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三个注解的组合,这里需要特殊强调下@EnableAutoConfiguration这个注解,没错就是这个注解使SpringBoot完成自动配置的。@EnableAutoConfiguration-----@Import(EnableAutoConfigurationImportSelector.class)-----AutoConfigurationImportSelector按照这个顺序我们可以进入SpringBoot的自动配置导入选择器。接下来我们就看一下SpringBoot是如何完成自动配置并观摩下源码。
1 public String[] selectImports(AnnotationMetadata annotationMetadata) { //进行选择导入 2 if (!isEnabled(annotationMetadata)) { //判断原数据是否为空为空返回空不为空进行导入相关操作 3 return NO_IMPORTS; 4 } 5 try { 6 AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader 7 .loadMetadata(this.beanClassLoader); 8 AnnotationAttributes attributes = getAttributes(annotationMetadata); //加载并获取属性 9 List<String> configurations = getCandidateConfigurations(annotationMetadata, //获取配置信息 10 attributes); 11 configurations = removeDuplicates(configurations); 12 configurations = sort(configurations, autoConfigurationMetadata); 13 Set<String> exclusions = getExclusions(annotationMetadata, attributes); 14 checkExcludedClasses(configurations, exclusions); 15 configurations.removeAll(exclusions); 16 configurations = filter(configurations, autoConfigurationMetadata); //从11行到16进行移除未完全集成的配置并进行排序和过滤 17 fireAutoConfigurationImportEvents(configurations, exclusions); //导入过滤后的组件 18 return configurations.toArray(new String[configurations.size()]); 19 } 20 catch (IOException ex) { 21 throw new IllegalStateException(ex); 22 } 23 }
上面代码是进行自动配置的主方法,其实操作流程我在注释上已经进行了简单的说明
1.先对原数据进行判断是否为空再进行具体操作
2.加载原数据并获取属性
3.获取配置信息 (其实最重要的就是第三点因为如何获取配置信息并进行加载才是我们最关心的也是SpringBoot中最核心的部分)
4.移除未完全集成的配置并进行排序过滤 (由于有些配置SpringBoot并没有给我们进行完全配置,需要我们自己进行手动配置,这里之所以这么做个人认为如果SpringBoot把所有的组件都进行集成那么对项目本身启动来说就会造成一定的压力,毕竟有些组件在有些项目中并不需要使用)
5.导入处理后的组件配置
这里我们需要着重强调下getCandidateConfigurations这个方法,看看SpringBoot是如何获取组件的。
1 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, 2 AnnotationAttributes attributes) { 3 List<String> configurations = SpringFactoriesLoader.loadFactoryNames( //Spring工厂进行加载获取配置信息 4 getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); 5 Assert.notEmpty(configurations, 6 "No auto configuration classes found in META-INF/spring.factories. If you " 7 + "are using a custom packaging, make sure that file is correct."); //如果配置不为空返回配置信息否则说明在META-INF/spring.factories这个目录下没有找到配置信息 8 return configurations; 9 }
1 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; 2 3 4 public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { 5 String factoryClassName = factoryClass.getName(); 6 try { 7 Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : //获取资源路径 8 ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); 9 List<String> result = new ArrayList<String>(); 10 while (urls.hasMoreElements()) { //如果存在将资源存入结果集中 11 URL url = urls.nextElement(); 12 Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); 13 String factoryClassNames = properties.getProperty(factoryClassName); 14 result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); 15 } 16 return result; 17 } 18 catch (IOException ex) { 19 throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + 20 "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); 21 } 22 }
相信看到这里已经不需要我过多的说明了,简而言之就是SpringBoot会去"META-INF/spring.factories"目录中去获取配置信息,然后再去做自动配置,现在我们在回过头来看最初SpringBoot进行自动配置的方法,我们走debug看一下。
这里我们可以看到SpringBoot在没有进行移除和过滤之前他在目录中获取到了96个组件下面再看一下过滤之后的。
过滤之后还有20个,也就是说SpringBoot为我们完全集成并自动配置的有20个组件,如果需要其他组件我们自己进行手动配置。(版本不动支持的组件数量或许有变化这里我是用的是1.5.9的版本)
除了这种方式还有其他方式来确定SpringBoot为我们自动配置了哪些组件么?如果这样看的话确实麻烦了写毕竟我们不可能每次都要在启动的时候通过debug来确认哪些是否被自动配置了,SpringBoot提供了debug启动模式让我们在控制台中就可以看到哪些进行了自动配置哪些没有完成自动配置,话不多说上图
Positive matches: 已经自动配置的 Negative matches:没有自动配置,以上就是SpringBoot如何完成自动配置的,其实自动配置这块想了好久要不要写,毕竟SpringBoot核心的配置,也怕有些地方写错了会误导其他人,也希望看到这篇文章的,看到有错误的地方希望能指正出来,互相学习互相进步,我不是一个勤快的人,但我希望能够改变当前懒散的状态,直到现在还记的我大学老师的一句话,只要开始永远不晚,只要努力就会成功,或许有鸡汤的成分,但还是希望只要开始永远不晚。
在很长的一段时间我变的颓废混日子,甚至忘了当初选择这个行业的初衷,总是喜欢抱怨种种得不公,我希望以后的日子我能找回那个努力的自己,没有人愿意平平淡淡,碌碌无为过一生,不求无愧于他人,但求无愧于自己,也希望每个在这个行业里为之坚持的伙伴我们都能无愧于自己,成为那个想象中的自己。
加载全部内容