自动装配原理(@SpringBootApplication)
启动类中,@SpringBootApplication
的作用是标注这个类是一个spring boot应用,启动类下的所有资源以及导入资源
spring boot所有的自动配置都在启动时扫描并加载的,所有自动配置的类都保存在spring.factories中,这些自动配置的类中都有
ConditionalOnXXX
注解,该注解的作用是对其中的条件进行判断,如成立,只要导入了对应的start,spring boot就有了相应的启动器,即自动装配生效
进到 @SpringBootApplication
中,可以看到这三个注解(以下内容一边看源码一起食用为佳)
@SpringBootConfiguration
-@Configuration
-@Component
@EnableAutoConfiguration
:自动导入包@ComponentScan
:扫描当前主启动类同级的包
具体步骤
-
spring boot启动时加载主配置类,开启了自动配置功能
@EnableAutoConfiguration
-
@EnableAutoConfiguration
作用:- 用
@EnableAutoConfigurationImportSelector
给容器导入一些组件 - 再进到父类
AutoConfigurationImportSelector
中,可以看到selectImports()
的内容(作用是获取候选的配置):
我们找到List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
SpringFactoriesLoader.loadFactoryNames
并进去loadFactoryNames
然后找到FACTORIES_RESOURCE_LOCATION
并进去可以看到对应了一个路径下的一个文件
综上所述可以看出,该注解的功能是扫描jar包类路径下META-INF/spting.factories
,把扫描到的这些文件的内容包装成properties对象,从properties中获取到EnableAutoConfiguration.class
类(类名)对应的值,然后将其添加在容器中;即将类路径下META-INF/spting.factories中配置的所有EnableAutoConfiguration.class的值加入到容器中
- 用
-
进/spting.factories中,有很多的自动配置类
全部都是以
xxxAutoConfiguration
命名的,都是容器中的组件并加入到容器中,spring boot使用他们来做自动配置,每一个自动配置类进行自动配置功能下面就以其中的
HttpEncodingAutoConfiguration
为例来解释自动配置原理(进入到该类中)
-
@Configuration(proxyBeanMethods = false)
表示这是个配置类,像配置文件一般,向容器中添加组件 -
@EnableConfigurationProperties(ServerProperties.class)
启动指定类的ConfigurationProperties
功能进到
ConfigurationProperties
中,即从配置文件中获取指定的值和bean的属性进行绑定;可以看到可配置的前缀是sever
,该类中有很多属性,第一个便是配置端口的server.port
所有在配置文件中能配置的属性都是在xxxProperties类中封装的,配置文件能配置什么就可以参照某个功能对应的这个属性类
@Conditional
是Spring底层的注解,作用是根据不同的条件进行判断,如果满足指定条件,整个配置类中的配置生效-
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
判断当前应用是否是web应用,是则当前配置类生效 -
@ConditionalOnClass(CharacterEncodingFilter.class)
判断当前项目有无该类,CharacterEncodingFilter
是SpringMVC中解决乱码的过滤器 -
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
哦按段配置文件中是否存在某个配置server.servlet.encoding.enabled
;如果不存在,判断也成立,及时我们配置文件中没有配置server.servlet.encoding.enabled=true
,也是默认生效的
根据这些,我们就能在配置文件中来配置属性,如#我们能配置的属性都是来源于这个功能的properties类 spring.http.encoding.enabled=true spring.http.encoding.charset=utf-8 spring.http.encoding.force=true
根据当前不同条件的判断,决定这个配置类是否生效,依但这个配置类生效,这个配置类就会给容器添加各种组件,这些组件的属性是哦才能够对应的properties类中获取的,这些类中的每个属性又是和配置文件绑定的
-
总结
- spring boot启动时会加载大量的自动配置类
- 我们先看我们所需的功能spring boot是否是默认写好的自动配置类
- 再看这个自动配置类中到底配置了什么组件(如果存在我们所需的组件,我们就无需再配置)
- 给容器中自动配置类添加组件时,会从properties类中获取某些属性,我们就可以再配置文件中指定这些属性的值
xxxAutoConfiguration(自动配置类):给容器添加组件
xxxProperties:封装配置文件中相关属性
@Conditional
解析
作用:必须是@Conditional
指定的条件成立,才能给容器中添加组件,配置中的所有内容才生效
@Conditional
扩展注解
注解类型 | 判断条件 |
---|---|
@ConditionalOnJava | 系统的java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean |
@ConditionalOnMissingBean | 容器中不存在指定Bean |
@ConditionalOnExpression | 满足SpEL表达式指定 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean/这个Bean是首选的 |
@ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前是web环境 |
@ConditionalOnNotWebApplication | 当前不是web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
由此我们知道自动配置类必须再一定的条件才能生效,那么我们怎么知道是否生效呢?我们可以通过再properties中启动debug=true属性,让控制台打印自动配置报告,通过报告,我们就知道那些自动配置生效了
Positive matches:自动配置配启用
Negative matches:自动配置配未启用,没有匹配成功