自动配置
Spring boot为了自动配置,增加了注解@EnableAutoConfiguration。一般只需要配置@SpringBootApplication即可,为什么呢?
很明显的,这个注解就是三个常用在一起的注解@SpringBootConfiguration,@EnableAutoConfiguration以及@ComponentScan的组合。
@SpringBootConfiguration这个注解实际上和@Configuration有相同的作用,配备了该注解的类就能够以JavaConfig的方式完成一些配置,可以不再使用XML配置。
@ComponentScan这个注解完成的是自动扫描的功能,相当于Spring XML配置文件中的:<context:component-scan>,可以使用basePackages属性指定要扫描的包,以及扫描的条件。如果不设置的话默认扫描@ComponentScan注解所在类的同级类和同级目录下的所有类,所以对于一个Spring Boot项目,一般会把入口类放在顶层目录中,这样就能够保证源码目录下的所有类都能够被扫描到。
@EnableAutoConfiguration开启自动配置,主要作用就是调用Spring-Core包里的 loadFactoryNames(),将autoconfig 包里的已经写好的自动配置加载进来。
@EnableAutoConfiguration注解代码如下:
这个注解是让Spring Boot的配置能够如此简化的关键性注解。通过@Import注释导入。让我们来查看EnableAutoConfigurationImportSelector.class的源码:
EnableAutoConfigurationImportSelector继承了AutoConfigurationImportSelector。进入他的父类AutoConfigurationImportSelector。找到selectImports()方法,他调用了getCandidateConfigurations()方法,在这里,这个方法又调用了Spring Core包中的loadFactoryNames()方法。这个方法的作用是,会查询META-INF/spring.factories文件中包含的JAR文件。
当找到spring.factories文件后,SpringFactoriesLoader将查询配置文件命名的属性。
Jar文件在org.springframework.boot.autoconfigure的spring.factories
spring.factories内容如下(截取部分),在这个文件中,可以看到一系列Spring Boot自动配置的列表:
Debug可以看出已经成功将各个配置类读取。
之后springboot会有一个排除机制,会根据pom文件中的启动器将一些没有使用到的配置类过滤,如下:
原先100个过滤之后就剩38个了。可以看出每个配置类命名格式为“xxxAutoConfiguration”。
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
自动配置精髓
1、Spring Boot 启动时会加载大量的自动配置类
2、看需要的功能有没有在 Spring Boot 默认写好的自动配置类中;
3、再看自动配置类中到底配置了哪些组件;(只要已经包含了要用的组件,则无需再配置)
4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,可以在配置文件中指定这些属性的值;
例子讲解HttpEncodingAutoConfiguration
Spring Boot的自动配置是基于类型安全配置,在application.properties直接配置可以覆盖该配置类的默认值
每一个自动配置类进行自动配置功能,以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理:
@EnableConfigurationProperties(HttpEncodingProperties.class)
//开启配置属性的注入,通过@EnableConfigurationProperties声明,自动映射一个POJO到Spring Boot配置文件(默认是application.properties文件)的属性集
@ConditionalOnWebApplication
//这个注解的意思就是判断当前是不是web应用,@Conditional是spring底层,意思就是根据不同的条件,来进行自己不同的条件判断,如果满足指定的条件,那么整个配置类里边的配置才会生效。
@ConditionalOnClass(CharacterEncodingFilter.class)
//@ConditionOnClass激活一个配置,当类路径中存在这个类时才会配置该类。这个CharacterEncodingFilter类是SpringMVC中乱码解决的过滤器
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
//来判断配置文件中是否存在某个配置,就是是否存在spring.http.encoding.enabled这个配置,matchIfMissing的意思就是如果不存在也认为这个判断是正确的
@Bean
//配置CharacterEncodingFilter这个Bean
@ConditionalOnMissingBean(CharacterEncodingFilter.class)
//@ConditionalOnMissingBean启用一个Bean定义,但必须是这个Bean之前未定义过才有效。容器中没有CharacterEncodingFilter这个Bean才会执行下面代码
这个HttpEncodingAutoConfiguration只有一个有参构造器,在只有一个有参构造器的情况下,参数的值就会从容器中拿。
着重了解@Conditional注释,Spring 4框架的新特性
此注释使得只有在特定条件满足时才启用一些配置。SpringBoot的AutoConfig大量使用了@Conditional,它会根据运行环境来动态注入Bean。这里介绍一些@Conditional的使用和原理,并自定义@Conditional来自定义功能。
@Conditional是SpringFramework的功能,SpringBoot在它的基础上定义了
@ConditionalOnClass,@ConditionalOnProperty等一系列的注解来实现更丰富的内容。
具体几个@Conditon*注解的含义
@ConditionalOnBean
仅仅在当前上下文中存在某个对象时,才会实例化一个Bean
@ConditionalOnClass
某个class位于类路径上,才会实例化一个Bean,该注解的参数对应的类必须存在,否则不解析该注解修饰的配置类
@ConditionalOnExpression
当表达式为true的时候,才会实例化一个Bean
@ConditionalOnMissingBean
仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean,该注解表示,如果存在它修饰的类的bean,则不需要再创建这个bean,可以给该注解传入参数例如@ConditionOnMissingBean(name = "example"),这个表示如果name为“example”的bean存在,这该注解修饰的代码块不执行
@ConditionalOnMissingClass
某个class类路径上不存在的时候,才会实例化一个Bean
@ConditionalOnNotWebApplication
不是web应用时,才会执行
Properties系列注释
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "spring.http.encoding")
//在application.properties配置的时候前缀是spring.http.encoding
自动配置报告
自动配置类必须在一定的条件下才能生效;怎么知道哪些自动配置类生效呢?可以通过启用 debug=true属性,来让控制台打印自动配置报告,这样就可以很方便的知道哪些自动配置类生效;
总结
SpringBoot的自动配置得益于SpringFramework强大的支撑,框架早已有很多工具和注解可以自动装配Bean。SpringBoot通过一个个封装,将市面上通用的组件直接写好了配置类。当我们程序去依赖了这些组件的jar包后,启动SpringBoot应用,于是自动加载开始了。
我们也可以定义自己的自动装配组件,依赖之后,Spring直接可以加载我们定义的starter。