您好,登錄后才能下訂單哦!
前言
大家應該都有所了解,隨著Ruby、Groovy等動態語言的流行,相比較之下Java的開發顯得格外笨重。繁多的配置、低下的開發效率、復雜的部署流程以及第三方技術集成難度大等問題一直被人們所詬病。隨著Spring家族中的新星Spring Boot的誕生,這些問題都在逐漸被解決。
個人覺得Spring Boot中最重要的兩個優勢就是可以使用starter簡化依賴配置和Spring的自動配置。下面這篇文章將給大家詳細介紹Spring Boot自動配置的相關內容,話不多說,來一起看看詳細的介紹。
使用starter簡化依賴配置
Spring提供了一系列starter來簡化Maven配置。其核心原理也就是Maven和Gradle的依賴傳遞方案。當我們在我們的pom文件中增加對某個starter的依賴時,該starter的依賴也會自動的傳遞性被依賴進來。而且,很多starter也依賴了其他的starter。例如web starter就依賴了tomcat starter,并且大多數starter基本都依賴了spring-boot-starter。
Spring自動配置
Spring Boot會根據類路徑中的jar包、類,為jar包里的類自動配置,這樣可以極大的減少配置的數量。簡單點說就是它會根據定義在classpath下的類,自動的給你生成一些Bean,并加載到Spring的Context中。自動配置充分的利用了spring 4.0的條件化配置特性,能夠自動配置特定的Spring bean,用來啟動某項特性。
條件化配置
假設你希望一個或多個bean只有在某種特殊的情況下才需要被創建,比如,一個應用同時服務于中美用戶,要在中美部署,有的服務在美國集群中需要提供,在中國集群中就不需要提供。在Spring 4之前,要實現這種級別的條件化配置是比較復雜的,但是,Spring 4引入了一個新的@Conditional注解可以有效的解決這類問題。
@Bean @Conditional(ChinaEnvironmentCondition.class) public ServiceBean serviceBean(){ return new ServiceBean(); }
當@Conditional(ChinaEnvironmentCondition.class)
條件的值為true的時候,該ServiceBean才會被創建,否則該bean就會被忽略。
@Conditional指定了一個條件。他的條件的實現是一個Java類——ChinaEnvironmentCondition,要實現以上功能就要定義ChinaEnvironmentCondition類,并繼承Condition接口并重寫其中的matches方法。
class ChinaEnvironmentCondition implements Condition{ public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment env = context.getEnvironment(); return env.containProperty("ENV_CN"); } }
在上面的代碼中,matches方法的內容比較簡單,他通過給定的ConditionContext對象進而獲取Environment對象,然后使用該對象檢查環境中是否存在ENV_CN屬性。如果存在該方法則直接返回true,反之返回false。當該方法返回true的時候,就符合了@Conditional指定的條件,那么ServiceBean就會被創建。反之,如果環境中沒有這個屬性,那么這個ServiceBean就不會被創建。
除了可以自定義一些條件之外,Spring 4本身提供了很多已有的條件供直接使用,如:
@ConditionalOnBean @ConditionalOnClass @ConditionalOnExpression @ConditionalOnMissingBean @ConditionalOnMissingClass @ConditionalOnNotWebApplication
Spring Boot應用的啟動入口
自動配置充分的利用了spring 4.0的條件化配置特性,那么,Spring Boot是如何實現自動配置的?Spring 4中的條件化配置又是怎么運用到Spring Boot中的呢?這要從Spring Boot的啟動類說起。Spring Boot應用通常有一個名為*Application的入口類,入口類中有一個main方法,這個方法其實就是一個標準的Java應用的入口方法。一般在main方法中使用SpringApplication.run()
來啟動整個應用。值得注意的是,這個入口類要使用@SpringBootApplication注解聲明。@SpringBootApplication是Spring Boot的核心注解,他是一個組合注解。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { // 略 }
@SpringBootApplication是一個組合注解,它主要包含@SpringBootConfiguration、@EnableAutoConfiguration等幾個注解。也就是說可以直接在啟動類中使用這些注解來代替@ SpringBootApplication注解。 關于Spring Boot中的Spring自動化配置主要是@EnableAutoConfiguration的功勞。該注解可以讓Spring Boot根據類路徑中的jar包依賴為當前項目進行自動配置。
至此,我們知道,Spring Boot的自動化配置主要是通過@EnableAutoConfiguration來實現的,因為我們在程序的啟動入口使用了@SpringBootApplication注解,而該注解中組合了@EnableAutoConfiguration注解。所以,在啟動類上使用@EnableAutoConfiguration注解,就會開啟自動配置。
那么,本著刨根問底的原則,當然要知道@EnableAutoConfiguration又是如何實現自動化配置的,因為目前為止,我們還沒有發現Spring 4中條件化配置的影子。
EnableAutoConfiguration
其實Spring框架本身也提供了幾個名字為@Enable開頭的Annotation定義。比如@EnableScheduling、@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和這些注解其實是一脈相承的。
下面是EnableAutoConfiguration注解的源碼:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { //略 }
觀察@EnableAutoConfiguration可以發現,這里Import了@EnableAutoConfigurationImportSelector,這就是Spring Boot自動化配置的“始作俑者”。
至此,我們知道,至此,我們知道,由于我們在Spring Boot的啟動類上使用了@SpringBootApplication注解,而該注解組合了@EnableAutoConfiguration注解,@EnableAutoConfiguration是自動化配置的“始作俑者”,而@EnableAutoConfiguration中Import了@EnableAutoConfigurationImportSelector注解,該注解的內部實現已經很接近我們要找的“真相”了。
EnableAutoConfigurationImportSelector
EnableAutoConfigurationImportSelector的源碼在這里就不貼了,感興趣的可以直接去看一下,其實實現也比較簡單,主要就是使用Spring 4 提供的的SpringFactoriesLoader工具類。通過SpringFactoriesLoader.loadFactoryNames()
讀取了ClassPath下面的META-INF/spring.factories文件。
這里要簡單提一下spring.factories文件,它是一個典型的java properties文件,配置的格式為Key = Value形式。
EnableAutoConfigurationImportSelector通過讀取spring.factories
中的key為org.springframework.boot.autoconfigure.EnableAutoConfiguration
的值。如spring-boot-autoconfigure-1.5.1.RELEASE.jar中的spring.factories文件包含以下內容:
# Auto Configure 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.webservices.WebServicesAutoConfiguration
上面的EnableAutoConfiguration配置了多個類,這些都是Spring Boot中的自動配置相關類;在啟動過程中會解析對應類配置信息。每個Configuation都定義了相關bean的實例化配置。都說明了哪些bean可以被自動配置,什么條件下可以自動配置,并把這些bean實例化出來。
如果我們新定義了一個starter的話,也要在該starter的jar包中提供 spring.factories文件,并且為其配置org.springframework.boot.autoconfigure.EnableAutoConfiguration
對應的配置類。
Configuation
我們從spring-boot-autoconfigure-1.5.1.RELEASE.jar中的spring.factories文件隨便找一個Configuration,看看他是如何自動加載bean的。
@Configuration @AutoConfigureAfter({JmxAutoConfiguration.class}) @ConditionalOnProperty( prefix = "spring.application.admin", value = {"enabled"}, havingValue = "true", matchIfMissing = false ) public class SpringApplicationAdminJmxAutoConfiguration { @Bean @ConditionalOnMissingBean public SpringApplicationAdminMXBeanRegistrar springApplicationAdminRegistrar() throws MalformedObjectNameException { String jmxName = this.environment.getProperty("spring.application.admin.jmx-name", "org.springframework.boot:type=Admin,name=SpringApplication"); if(this.mbeanExporter != null) { this.mbeanExporter.addExcludedBean(jmxName); } return new SpringApplicationAdminMXBeanRegistrar(jmxName); } }
看到上面的代碼,終于找到了我們要找的東西——Spring 4的條件化配置。上面SpringApplicationAdminJmxAutoConfiguration在決定對哪些bean進行自動化配置的時候,使用了兩個條件注解:ConditionalOnProperty和ConditionalOnMissingBean。只有滿足這種條件的時候,對應的bean才會被創建。這樣做的好處是什么?這樣可以保證某些bean在沒滿足特定條件的情況下就可以不必初始化,避免在bean初始化過程中由于條件不足,導致應用啟動失敗。
總結
至此,我們可以總結一下Spring Boot的自動化配置的實現:
通過Spring 4的條件配置決定哪些bean可以被配置,將這些條件定義成具體的Configuation,然后將這些Configuation配置到spring.factories文件中,作為key: org.springframework.boot.autoconfigure.EnableAutoConfiguration
的值,這時候,容器在啟動的時候,由于使用了EnableAutoConfiguration注解,該注解Import的EnableAutoConfigurationImportSelector會去掃描classpath下的所有spring.factories文件,然后進行bean的自動化配置。
所以,如果我們想要自定義一個starter的話,可以通過以上方式將自定義的starter中的bean自動化配置到Spring的上下文中,從而避免大量的配置。
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對億速云的支持
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。