1.话题引入
在SpringBoot开发中,application.properties/application.yml配置文件中能够写啥配置,如何写呢,我们可以通过查询官方文档得知https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/htmlsingle/#common-application-properties
但试想,总是通过查询文档或通过工具提示,硬记,都是比较麻烦的,如果知道自动配置原理,那就简单多了。
2.自动配置原理
1.我们的SpringBoot启动都是通过启动类启动的,在启动类上加一个@SpringBootApplication注解就表示这是一个启动类,那么我们就看看这个注解,进入到其中,发现这个注解上还有一个@EnableAutoConfiguration注解
通过@EnableAutoConfiguration注解开启自动配置功能
2.那么@EnableAutoConfiguration这个注解的作用又是啥呢?下面就进入到这个注解看看
可以看到,这个注解上有通过@Import注解向容器中导入一些组件,其中AutoConfigurationImportSelector(其实他是ImportSelector的一个实现类,ImportSelector中定义了selectImports方法,通过实现这个方法,返回一个String[],数组中定义的是bean的全类名,就可以向IOC容器中导入组件)就配置了导入哪些组件,进入到AutoConfigurationImportSelector中找到selectImports()方法的实现
可以看到通过getCandidateConfigurations(annotationMetadata,attributes);获得候选配置,最终返回这个configurations,进入到getCandidateConfigurations(annotationMetadata,attributes);方法中
通过SpringFactoriesLoader.loadFactoryNames()获得bean,进入到loadFactoryNames()方法
会通过classLoader.getResources(FACTORIES_RESOURCE_LOCATION)获得到所有jar包类路径下的META-INF/spring.factories文件的路径,通过循环将这些文件的内容包装为Properties,通过Properties获得文件中的值,最终返回。但在我们调用SpringFactoriesLoader.loadFactoryNames()方法时,通过getSpringFactoriesLoaderFactoryClass()方法传入一个EnableAutoConfiguration,意思是在Properties中获得EnableAutoConfiguration类对应的值,然后把它们添加在容器中。
3.我们在spring-boot-autoconfigure-2.0.6.RELEASE.jar中找到了对应的文件(当然其他jar中也有对应的文件,但是文件中没有EnableAutoConfiguration类对应的值)及EnableAutoConfiguration对应的值
最终,就是将EnableAutoConfiguration下对应的所有组件加入到IOC容器中,每一个xxxAutoConfiguration类都是容器中的一个组件,作用就是用他们做自动配置。
4.每一个自动配置类进行自动配置功能,我们以一个简单的配置类HttpEncodingAutoConfiguration为例讲解
这个类上标了很多的注解,@Configuration表示这是一个配置类,@EnableConfigurationProperties(HttpEncodingProperties.class)启用指定类的ConfigurationProperties功能,并将指定类加入到IOC容器中,进入HttpEncodingProperties类中
从配置文件中获的以spring.http.encoding开头的配置装配到这个类的对应属性上,所以application.properties/application.yml配置文件中能配置啥都在xxxProperties类中封装着。@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)是基于Spring的@Conditional注解实现的,可以根据不同的条件确定配置类是否生效(当条件瞒足时生效),而@ConditionalOnWebApplication这个注解就是判断当前应用是否是web应用,如果是则当前配置类生效。@ConditionalOnClass(CharacterEncodingFilter.class)也是一个判断,判断当前的jar包中是否有CharacterEncodingFilter这个类,CharacterEncodingFilter这个类似SpringMVC中进行乱码解决的拦截器。@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)判断配置文件中是否存在spring.http.encoding.enableb配置项,matchIfMissing = true表示如果配置不存在,这个判断也是正确的。总而言之就是通过判断决定这个配置类是否生效,一旦生效,那么配置类中又干了写啥?
HttpEncodingAutoConfiguration这个自动配置类就通过@Bean的方式向容器中添加CharacterEncodingFilter组件,这个组件的某些值是通过HttpEncodingProperties获得的,HttpEncodingAutoConfiguration只有一个有参构造器,IOC容器在为它创建对象时就会为它注入HttpEncodingProperties,而HttpEncodingProperties又与SpringBoot的配置文件映射了,所以可以获得配置文件中配置的值。
4.前面我们想扫描到了很多的自动配置类,那么这些配置类都会生效吗?答案是否定的
随便举两个例子:可以看到这两个配置类的上面都加有@Conditionalxxx的注解,也就是说,只有环境瞒足了条件才会向容器中加入自动配置组件,自动配置类才会生效。通过在配置文件中配置debug=true开启SpringBoot的debug功能,这样在项目启动时就可以知道哪些自动配置类生效了
3.SpringBoot精髓
1.SpringBoot在启动的时候加载了大量的配置类
2.有没有我们需要的自动配置类
3.如果有,查看配置中到底配置了那些组件,有要用的组件,就不要配置
4.如果没有就需要自己写配置类
5.给容器中加组件的时候,会从xxxProperties文件中获得配置的属性,这些属性就可以这配置文件中指定