javascript
Spring Boot自动配置原理分析
一、寫在前面
隨著時間的遷移Spring Boot 越來越多的出現在Java 后端程序員的視野中,Spring Boot 之所以會那么流行,很大的一個原因是自身集成了很多的Bean,簡化了傳統Sring 項目瑣碎的文件配置。
這些自動配置的Bean 在入口類啟動的時候完成注入,并由Spring 的IoC 容器管理。所以在使用某些Bean的時候,不需要再由我們自動配置。下面我們就通過源碼的方式來看看Spring Boot 是如何實現自動配置的。
二、查看自動配置的Bean
我們可以在Spring Boot 項目的配置文件(application.properties,application.yml)中設置一個屬性debug=true,設置完成后再啟動Spring Boot 的入口類,就會在控制臺輸出有哪些Bean 已經完成了自動配置。
簡單的截了一些如下圖:
三、自動配置的原理分析
1.我們從入口類開始分析,我們都知道Spring Boot 項目一般會有一個入口類,這個入口類有一個很重要的特征就是加上了@SpringBootApplication注解。
@SpringBootApplication 是一個組合注解,如下:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan其中有一個重要的注解@EnableAutoConfiguration,這個注解的作用就是用于啟用Spring Boot 的自動配置。
2.接著具體查看@EnableAutoConfiguration,其實它也是一個組合注解,如下:
@SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class)有一個注解@Import(EnableAutoConfigurationImportSelector.class),在這個注解中有一個導入自動配置的選擇器,用于導入自動配置的Bean。
下面就來分析這個EnableAutoConfigurationImportSelector都做了什么。
3.EnableAutoConfigurationImportSelector類繼承自AutoConfigurationImportSelector,在這個類中只有一個方法,用于判斷是否啟動了自動配置。
@Deprecated public class EnableAutoConfigurationImportSelectorextends AutoConfigurationImportSelector {@Overrideprotected boolean isEnabled(AnnotationMetadata metadata) {if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,true);}return true;}}那么我們就來看看它的父類AutoConfigurationImportSelector。
4.在AutoConfigurationImportSelector類中有一個selectImports()方法,如下:
@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}try {AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AnnotationAttributes attributes = getAttributes(annotationMetadata);// 用于獲取自動配置的相關信息List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);configurations = removeDuplicates(configurations);configurations = sort(configurations, autoConfigurationMetadata);/*** 獲得移除的自動配置信息* 如果我們不想讓Spring Boot 自動配置一些Bean, 我們可以使用在入口類的注解中使用exclude 聲明* 比如:@SpringBootApplication(exclude = {DispatcherServlet.class})*/Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return configurations.toArray(new String[configurations.size()]);}catch (IOException ex) {throw new IllegalStateException(ex);}}我們主要查看上面方法中的getCandidateConfigurations(annotationMetadata, attributes)方法,
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes) {// 調用SpringFactoriesLoader 的loadFactoryNames() 方法,返回從類路徑下獲得自動配置相關的信息List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());// 判斷自動配置的信息是否為空,為空拋出異常,第二個參數為拋出的異常信息Assert.notEmpty(configurations,"No auto configuration classes found in META-INF/spring.factories. If you "+ "are using a custom packaging, make sure that file is correct.");return configurations;}下面接著查看loadFactoryNames()方法,
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {// factoryClass = EnableAutoConfiguration.class,可以通過上一步查看String factoryClassName = factoryClass.getName();try {/*** FACTORIES_RESOURCE_LOCATION 是一個編譯器期量值為:"META-INF/spring.factories"* 用于獲得所有jar 包類路徑下的META-INF下的spring.factories 文件的URL*/Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));List<String> result = new ArrayList<String>();while (urls.hasMoreElements()) {URL url = urls.nextElement();// 將掃面到文件中的內容包裝成一個Properties 對象Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));/*** 獲取EnableAutoConfiguration 類名在properties 中的值* 這些值對應的Bean 就是要添加到Spring 容器中的自動配置類*/String factoryClassNames = properties.getProperty(factoryClassName);result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));}return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);}}到這里就可知道Spring Boot 是如何實現自動配置的了,Spring Boot 會掃描到類路徑下的META-INF/spring.factories配置文件,把EnableAutoConfiguration對應的的Bean值添加到容器中。
5.接著我們就來看一下類路徑下META-INF/spring.factories配置文件,其中EnableAutoConfiguration對應的值都是有哪些。
下面是spring.factories配置文件中EnableAutoConfiguration對應的值,為了顯示的效果在這里只貼出一部分。我們可以發現一個規律,這些值一般都是以×××AutoConfiguration命名,每一個×××AutoConfiguration 都作為容器中的一個組件,被添加到IoC 容器中,從而實現Spring Boot 的自動配置。
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,\四、總結
這篇博文簡單的分析了Spring Boot 自動配置的原理,給大家提供一個參考的方向,關于其中的一些具體細節,大家可以自己查看底層的源碼進行了解,希望本篇博文能夠為你提供幫助。
總結
以上是生活随笔為你收集整理的Spring Boot自动配置原理分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么做镜像系统到u盘安装系统文件格式 U
- 下一篇: gradle idea java ssm