javascript
Spring Boot自动配置原理
要了解Spring Boot的自動配置首先我需要先了解Spring Boot的兩個機制,一個是配置文件如何進入到系統變成屬性,二是如何將這些屬性加入到容器中。
首先我們需要有一個組件,這個組件中的屬性將會承載我們在Properties配置文件中寫出的內容。比如:
public class PersonProperties {private String lastName;private Integer age;private Boolean boss; }spring boot提供了兩個注解@PropertySource()和@ConfigurationProperties;這兩個注解的意思分別是指定配置文件的位置和從配置文件中獲取值。具體可以看下面這個示例:
person.properties文件內容:
person.lastName = hello person.age = 11 person.boss = false @PropertySource(value = {"classpath:person.properties"}) @Component @ConfigurationProperties(prefix = "person") public class PersonProperties {private String lastName;private Integer age;private Boolean boss;public void setLastName(String lastName) {this.lastName = lastName;}public void setAge(Integer age) {this.age = age;}public void setBoss(Boolean boss) {this.boss = boss;}@Overridepublic String toString() {return "Person{" +"lastName='" + lastName + '\'' +", age=" + age +", boss=" + boss +'}';} }注意:@Component的加入是因為只有這個組件是容器中的組件,才能容器提供的@ConfigurationProperties功能,你也可以先不用,后面再使用@EnableConfigurationProperties注解來使@ConfigurationProperties生效,也就是注入數據并加入容器。在后面自動配置中用的就是這種用法;并且在注入屬性的組件當中一定要寫set方法,否則配置文件的屬性無法注入;目前@PropertySource只能支持properties配置文件
按照道理來說,這個時候我們已經可以在項目中使用PersonProperties中的屬性了,但是Spring Boot中還是使用了配置類來將這些屬性再一次的封裝到具體的類中,比如獲取從容器中獲取的PersonProperties類中的屬性,將其賦給Person類,然后將Person也放到容器中。Spring Boot使用的是類似下面的這種操作(主要看注解和注釋)
@Configuration public class MyAppConfig {//將方法的返回值添加到容器中;容器中這個組件默認的id就是方法名@Beanpublic HelloService helloService02(){System.out.println("配置類@Bean給容器中添加組件了...");return new HelloService();} }了解了這兩種方式之后,我們就可以分析Spring Boot自動配置的原理了。
首先在@SpringBootApplication中我們使用了@EnableAutoConfiguration;
@EnableAutoConfiguration 會掃描所有jar包類路徑下 META‐INF/spring.factories,然后把掃描到的這些文件的內容包裝成properties對象從properties中獲取到EnableAutoConfiguration.class類(類名)對應的值,然后把他們添加在容器中,也即是類似下面的這些類加入到容器中(只是部分):
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ ...我們以其中的HttpEncodingAutoConfiguration為例:
@Configuration //表示這是一個配置類,以前編寫的配置文件一樣,也可以給容器中添加組件 @EnableConfigurationProperties(HttpEncodingProperties.class) //啟動指定類的ConfigurationProperties功能;將配置文件中對應的值和HttpEncodingProperties綁定起來;并把HttpEncodingProperties加入到ioc容器中 @ConditionalOnWebApplication //Spring底層@Conditional注解(Spring注解版),根據不同的條件,如果滿足指定的條件,整個配置類里面的配置就會生效; 判斷當前應用是否是web應用,如果是,當前配置類生效 @ConditionalOnClass(CharacterEncodingFilter.class) //判斷當前項目有沒有這個類CharacterEncodingFilter;SpringMVC中進行亂碼解決的過濾器; @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //判斷配置文件中是否存在某個配置 spring.http.encoding.enabled;如果不存在,判斷也是成立的即使我們配置文件中不配置pring.http.encoding.enabled=true,也是默認生效的;public class HttpEncodingAutoConfiguration {//他已經和SpringBoot的配置文件映射了private final HttpEncodingProperties properties;//只有一個有參構造器的情況下,參數的值就會從容器中拿public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {this.properties = properties;}@Bean //給容器中添加一個組件,這個組件的某些值需要從properties中獲取@ConditionalOnMissingBean(CharacterEncodingFilter.class) //判斷容器沒有這個組件?public CharacterEncodingFilter characterEncodingFilter() {CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));return filter;} }可以從注解中看到它是一個配置類,并且從容器中拿到一個叫HttpEncodingProperties的類,將它的屬性賦給filter,然后將filter也放到容器中,我們可以看看HttpEncodingProperties這個類是什么樣子的:
@ConfigurationProperties(prefix = "spring.http.encoding") //從配置文件中獲取指定的值和bean的屬性進行綁定 public class HttpEncodingProperties {public static final Charset DEFAULT_CHARSET = Charset.forName("UTF‐8");...可以看到它就是和Properties文件直接打交道的類了,所以你可以知道一般xxxAutoConfiguration和一個xxxProperties是一對的,這樣一來Spring Boot就完成了配置過程。
總結
以上是生活随笔為你收集整理的Spring Boot自动配置原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM运行时数据区概览
- 下一篇: Spring Boot注册Servlet