再次点赞,力量无限。世界您好:)微信搜索“程序猿Alan”。本文已收录在Github.com/niumoo/JavaNotes和UnreadCodeBlog,有很多知识点和系列文章。注:本SpringBoot系列文章基于SpringBootv2.1.1.RELEASE版本进行学习分析,不同版本可能略有差异。前言关于配置文件的可配置内容,SpringBoot官网已经提供了完整的配置示例和说明。可以说SpringBoot的精髓之一就是自动配置,为开发节省了大量的配置时间,可以更快的融入到业务逻辑的开发中。那么自动配置是如何实现的呢?1.@SpringBootApplication跟随SpringBoot启动类注解@SpringBootApplication跟踪源码寻找自动配置的原理。@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@interfaceSpringBootApplication{@EnableAutoConfiguration启用自动配置。@ComponentScan开启注解扫描从SpringBootApplication我们可以发现,这是一个简单的注解配置,包含自动配置、配置类、包扫描等一系列功能。2.@EnableAutoConfiguration继续跟踪,查看@EnableAutoConfiguration的源码,里面比较重要的是@Import,它引入了一个翻译名为自动配置的选择器的类。这个类实际上是一个自动配置的加载选择器。@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})public@interfaceEnableAutoConfiguration{StringENABLED_OVERRIDE_PROPERTY="spring.boot.enableautoconfiguration";类>[]排除()默认{};String[]excludeName()default{};}继续跟踪AutoConfigurationImportSelector.class。该类中有一个重要的方法getCandidateConfigurations。用于加载SpringBoot配置的自动配置类。getAutoConfigurationEntry过滤掉有效的自动配置类。protectedAutoConfigurationEntrygetAutoConfigurationEntry(AutoConfigurationMetadataautoConfigurationMetadata,AnnotationMetadataannotationMetadata){if(!isEnabled(annotationMetadata)){返回EMPTY_ENTRY;}AnnotationAttributes属性=getAttributes(annotationMetadata);List配置=getCandidateConfigurations(annotationMetadata,attributes);配置=removeDuplicates(配置);Setexclusions=getExclusions(annotationMetadata,attributes);checkExcludedClasses(配置,排除);配置.removeAll(排除);配置=过滤器(配置,自动配置元数据);fireAutoConfigurationImportEvents(配置,排除);返回新的AutoConfigurationEntry(配置,排除);}受保护的列表getCandidateConfigurations(AnnotationMetadatametadata,AnnotationAttributesattributes){Listconfigurations=SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());Assert.notEmpty(configurations,"NoautoconfigurationclassesfoundinMETA.fact.fact/oriesyou"+"areusingacustompackaging,makesurethatfileiscorrect.");返回配置;}下图是在DEBUG模式下过滤后的结果,因为我只加了web模块,所以只有web相关的自动配置3.xxxAutoConfiguration和xxxProperties在上面的debug中,我们看到自动配置加载成功了。到目前为止,我们只看到了配置类,还没有找到自动配置值。只需选择一个AutoConfiguration即可查看源代码。这里我选择ServletWebServerFactoryAutoConfiguration.@Configuration@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)//判断当前项目是否有这个类//CharacterEncodingFilter;SpringMVC乱码解析过滤器;@ConditionalOnClass(ServletRequest.class)//Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果//满足指定的条件,则整个配置类中的配置生效;判断当前应用是否为web应用,如果是,则当前配置类生效class,ServletWebServerFactoryConfiguration.EmbeddedJetty.class,ServletWebServerFactoryConfiguration.EmbeddedUndertow.class})publicclassServletWebServerFactoryAutoConfiguration{需要注意的是@EnableConfigurationProperties(ServerProperties.class)。他的意思是启动指定类的ConfigurationProperties函数;将配置文件中对应的值绑定到ServerProperties;并将ServerProperties添加到IOC容器中。让我们再看看ServerProperties。@ConfigurationProperties(prefix="server",ignoreUnknownFields=true)publicclassServerProperties{/***服务器HTTP端口。*/私有整数端口;很明显,这里我们在属性映射文件properties一开始就使用ConfigurationProperties来绑定服务器。结合默认配置#pathspring-boot-autoconfigure-2.1.1.RELEASE.jar#/META-INF/spring-configuration-metadata.json{"name":"server.port","type":"java.lang.Integer","description":"ServerHTTPport.","sourceType":"org.springframework.boot.autoconfigure.web.ServerProperties","defaultValue":8080}达到自动配置的目的。4、自动配置小结SpringBoot启动时,会加载主配置类,并开启自动配置功能@EnableAutoConfiguration。@EnableAutoConfiguration将META-INF/spring.factories中定义的自动配置类导入到容器中。有效自动配置类的过滤器。每个自动配置类结合对应的xxxProperties.java读取自动配置功能的配置文件。5、配置类是自动配置的,我们发现它为我们省去了很多配置文件,那么在自定义配置的时候,需要写XML吗?虽然Springboot可以使用SpringApplicationXML文件进行配置,但我们通常使用@Configuration类来代替,这也是官方推荐的方式。5.1XML配置定义helloServiceBean.导入配置。@ImportResource(value="classpath:spring-service.xml")@SpringBootApplicationpublicclassBootApplication{publicstaticvoidmain(String[]args){SpringApplication.run(BootApplication.class,args);}}5.2这种方式的Annotation配置相当于上面的XML配置,也是官方推荐的方式。@Configuration注解的类(位于扫描包路径中)将被扫描。/****配置类,相当于传统Spring开发中的xml->bean配置**@Authorniujinpeng*@Date2018/12/70:04*/@ConfigurationpublicclassServiceConfig{/***默认添加到容器的ID是方法名(helloService)**@return*/@BeanpublicHelloServicehelloService(){returnnewHelloService();}}6、附录@Conditional扩展注解功能(判断当前规范是否满足条件)@ConditionalOnJava系统的java版本是否满足要求@ConditionalOnBean容器中是否存在指定的bean;@ConditionalOnMissingBean容器中不存在指定的bean;@ConditionalOnExpression满足@ConditionalOnClass系统中指定的SpEL表达式。@ConditionalOnMissingClass系统中有一个指定的类。类@ConditionalOnSingleCandidate容器中只有一个指定的bean,或者这个bean是首选bean@ConditionalOnProperty系统中的指定属性是否有指定值@ConditionalOnResource类路径中是否存在指定的资源文件@ConditionalOnWebApplication当前是一个web环境@ConditionalOnNotWebApplication当前不是web环境@ConditionalOnJndiJNDI存在指定item文章代码已上传至GitHubSpringBoot自动配置。Helloworld:)我是Alan,一线技术工具人,认真写文章。喜欢的人都是有才华的,不仅长得帅气,说话也好听。文章持续更新中,可以关注公众号“程序猿艾伦”或访问“未读代码博客”。回复【资料】里面有我准备的各种系列的知识点和必读书籍。本文已收录于Github.com/niumoo/JavaNotes。知识点多,系列文章多。欢迎来到星空。