SpringBoot自动配置原理初探
SpringBoot配置原理初探
1、SpringBoot精华之处
springBoot最大的特点就是在spring的基础上,大规模的缩减了配置文件的数量,以往我们要手动配置n多个属性,现如今使用了boot,即使没有任何配置,代码依然跑得通,框架依然能够搭建起来。
2、配置原理一:springBoot的启动准备工作
既然如此,springBoot肯定是为我们配置好了绝大多数的信息,那它是什么时候配置的,在哪里配置的,怎么配置的,为什么配置了就可以管用?
根据图中指示,我们发现了这么多的xxxAutoConfiguration,这些就是自动配置类,springBoot就是通过获取的它们,才做到了自动配置。那么spingBoot怎么获取的?
点开springBoot的启动类,再点开它的@SpringBootApplication注解,找到如下这个注解
这个注解的功能如同字面意思一样,叫做开启自动配置功能,那再点进去
发现它导入了一样东西,叫做"选择器"类,再点进去
找到有这样一个方法:
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
这是获取到所有候选的配置,放入集合,最后将集合返回
那么整理下思路:boot项目启动时,它开启了自动配置,自动配置中用到了一个选择器,选择器获取到了所有的候选配置,boot启动就载入了这些候选配置,就是这样,有了自动配置的基础。
那接下来,点进上面的方法,再看看:
有个SpringFactoriesLoader.loadFactoryNames方法,毫不犹豫再点
loadFactoryNames调用了loadSpringFactories方法,而在这里,它将
"META-INF/spring.factories"这个路径下的url路径全都存了起来!
这个路径就是下面这茫茫多的xxxAutoConfiguration
总结1:springBoot一启动,就通过上述一系列注解和方法,找到所有的自动配置类
而现在只是找到了所有自动配置类,配置哪些类,配置的属性都是什么,值是多少,接下来springBoot还有话说
3、配置原理二:springBoot怎么选择需要的配置
这里举例说明:以一个上图中的HttpEncodingAutoConfiguration自动配置类举例
这个HttpEncodingAutoConfiguration,我们关注上图中的几点
1:@Configuration:说明这个是配置类
2:@EnableConfigurationProperties({HttpProperties.class}):这个注解是"开启配置属性",开启谁的?开启HttpProperties.class这个类的
什么意思呢?就是说我这个HttpEncodingAutoConfiguration自动配置类,需要用HttpProperties.class这个类里的属性值来完成配置!
再往下看类里面:
只有一个有参构造器,一个properties属性,这个properties由这个构造器注入值,也只有通过入参HttpProperties properties来赋值
那为什么一定要赋值,因为接下来要用啊,回到HttpEncodingAutoConfiguration再往下拉:
看到没,properties属性里的值要拿出来放到filter里,然后filter被返回,返回到哪儿去?
看这个方法头上的@Bean,被它标记了,返回值filter是要被注入到Ioc容器中的,而只有被注入到Ioc,配置才会真的生效
那么整理下思路:自动配置类(xxxAutoConfiguration)需要有属性和值,这些东西从哪儿来的?就是从@EnableConfigurationProperties({HttpProperties.class})来,EnableConfigurationProperties绑定了HttpProperties.class,将这里的属性和值注入到xxxAutoConfiguration类,并在该类中处理后通过@Bean注入到spring的Ioc容器中,使其生效
那就有个问题,开发人员并不是每次都使用所有的配置,如果每次都全部注入,很不合适,所以就应该考虑过滤掉那些当前开发人员不需要的配置,所以接下来看看HttpEncodingAutoConfiguration的另外两个需要我们关注的注解
3:@ConditionalOnClass({CharacterEncodingFilter.class})
这个注解就是判断用的,判断CharacterEncodingFilter.class这个类是否存在,如果不存在,那么刚才说的类的绑定、属性值的注入、向Ioc的注入都不会生效了。怎么算存不存在?就是看你的pom.xml文件有没有引入对应的依赖,如果没有引入,maven就没有导入包,那个对应的类也就不存在了
4:@ConditionalOnProperty( prefix = "spring.http.encoding", value = {"enabled"}, matchIfMissing = true)
这个也是判断用的,只不过是判断属性是否存在,判断什么属性?判断在哪儿是否存在?
这就该提及:springBoot默认有四个放置配置文件的地方,此处不过多展开,我们常用的是
这个注解判断的就是这里是否写了属性,什么属性?
prefix = "spring.http.encoding":前缀为spring.http.encoding的属性
只不过看matchIfMissing = true,即使没有写上面的属性,boot也默认设置了要去获取默认的值
至此,boot的自动配置已经完善了,一切准备就绪,只差我们给它提供需要配置的属性和值了
刚才说了,值从@EnableConfigurationProperties({HttpProperties.class})这里来,那么进入HttpProperties.class看看去
有@ConfigurationProperties( prefix = "spring.http")这个注解,boot就会从配置文件中获取前缀为"spring.http"的属性值。ConfigurationProperties的意思就是"配置属性"。
到此为止,这最后的一步,也是唯一需要我们做的,也都做好了
那都能配置哪些属性呢?
只要看看这个类里有什么属性就知道了,我们能配置的,都已经在类里写好了
来验证一下:
总结2:springBoot找到所有的自动配置类后,当然不能全部配置,因为你不一定都用得上,所以需要判断过滤掉不用的配置。确定以后,boot就通过自己的手段去配置文件里拿我们想要配置的属性了
说了这么多,其实最终的结论也就是总结1和总结2这么几句话。