Springboot專案中 如何獲取@Configuration註解標註的配置類
整個springboot並沒有在spring的基礎上提供什麼額外的功能。
從開發人員的角度來看,springBoot的最大作用就是引入某些jar包後,自動為spring上下文環境生成某些特定功能的Bean,這樣就可以自動提供某些相關功能。
從實現的角度來看,spring通過被標記了@Configuration的類提供一些提前生成好的Bean提供特別的功能,而用@Contional系列的註解限制生成的條件,通常就是@ConditionalOnClass和@ConditionalOnMissingBean註解的配合使用。前者確定某些功能需要的class已經有了,後者確定你沒有自己生成相關的bean,才提供預設的。
可以使用@AutoConfigureBefore,@AutoConfigureAfter,@AutoconfigureOrder 來確定某個自動註冊類的生效順序。作用類比@Order。
自動註冊一般提供2個module:一個是autoconfigure jar包,一個是starter jar包。其中starter這種jar裡面並沒有程式碼,是空的。唯一的作用是將需要的各種jar寫入構建檔案,這樣引入此starter,就不要再去關心相應的其他jar了。
springboot自己的starter實現是這麼幹的。
SpringCloudNetflixZuul是將這兩者統一於一個module中來實現的
主要分成以下三個場景:
-
@Configuration配置類在程式可以掃描到的package裡,也就是@ComponentScan註解所指定的package裡。SpringBoot工程天然支援該類配置類注入方式。
最佳實踐:
最佳實踐
//@SpringBootApplication註解中含有@ComponentScan 1 @SpringBootApplication 2 public class Application { 3 public static void main(String[] args) { 4 SpringApplication.run(Application.class, args); 5 } 6 }
-
@Configuration配置類沒有在package掃描路徑下,即不是專案開發人員自己編寫的程式碼。
比如製作第三方包供他人在springboot專案中使用,如RPC框架、starter工程、spring-cloud-netflix-zuul等。
最佳實踐:
1、編寫AutoConfiguration配置類
2、在META-INF/spring.factories裡用org.springframework.boot.autoconfigure.EnableAutoConfiguration來指定。
spring-boot-autoconfigure包裡的配置類都是通過這種方式引入的。
示例:
用於在專案中匯入的第三方包spring-cloud-netflix-zuul
image
image
引入spring-cloud-netflix-zuul的demo專案(實際是通過spring-cloud-starter-zuul引入的)
當然,這個方式需要程式使用@EnableAutoConfiguration註解,這個註解是通過AutoConfigurationImportSelector來掃描spring.factories檔案,把定義的配置類引入的。
讀取spring.factories檔案的實現
是通過org.springframework.core.io.support.SpringFactoriesLoader實現的。
SpringFactoriesLoader的實現類似於SPI(Service Provider Interface)java SPI提供一種服務發現機制,為某個介面尋找服務實現的機制。
有點類似IOC的思想,就是將裝配的控制權移到程式之外,在模組化設計中這個機制尤其重要。
實現說明:
1 @SpringBootApplication
2 public class Application {
3 public static void main(String[] args) {
4 SpringApplication.run(Application.class, args);
5 }
6 }
這是springboot專案中應用最常見的啟動方式,核心有兩個:
- @SpringBootApplication註解
- SpringApplication.run()靜態方法
和我們此處討論有關係的是註解@SpringBootApplication
@SpringBootApplication原始碼如下:
@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 {....}
@ComponentScan,spring的自動掃描註解,對應方法一。
@EnableAutoConfiguration:藉助@Import的幫助,將所有符合自動配置條件的bean定義載入到IoC容器(建議放在根包路徑下,這樣可以掃描子包和類)
@EnableAutoConfiguration原始碼如下:
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {....}
其核心是一個EnableAutoConfigurationImportSelector類
public class EnableAutoConfigurationImportSelector
extends AutoConfigurationImportSelector {...}
核心方法在頂級介面ImportSelector的selectImports()的實現上,原始碼如下:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
//1.從META-INF/spring-autoconfigure-metadata.properties檔案中載入配置屬性(有一些有預設值)
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//2.獲取註解屬性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//3.獲取自動配置類
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//4.移除重複的
configurations = removeDuplicates(configurations);
//5.排序
configurations = sort(configurations, autoConfigurationMetadata);
//6.排出需要排出的
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//6.過濾器OnClassCondition(註解中配置存在某類才生效)
configurations = filter(configurations, autoConfigurationMetadata);
//7.觸發自動配置匯入監聽事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
-
使用@Import註解
這個註解可以引入三種類
-
使用了@Configuration註解的類
如spring-cloud-netflix中ZuulProxyAutoConfiguration通過@import匯入了若干個被@Configuration註解的類
image
-
ImportSelector的子類(嚴格說來這不屬於被@Configuration標註的配置類這一前提,但也屬於springboot自動配置能力的一種,故羅列在此)
如@EnableAutoConfiguration中所引入的EnableAutoConfigurationImportSelector
image
-
ImportBeanDefinitionRegistrar的子類
{todo}
-
作者:Drew_Zhong
連結:https://www.jianshu.com/p/9ecdc9ad70dc
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
相關文章
- Springboot中註解@Configuration原始碼分析Spring Boot原始碼
- Java如何快速獲取類附帶的註解Java
- Spring-Boot專案中配置redis註解快取SpringbootRedis快取
- SpringBoot專案中獲取配置檔案的配置資訊Spring Boot
- Spring零配置之@Configuration註解詳解Spring
- @Configuration, @Bean 註解的作用Bean
- SpringBoot主配置和註解Spring Boot
- SpringBoot攔截器中獲取註解、攔截器中注入ServiceSpring Boot
- Spring Boot配置類的註解Spring Boot
- Spring管理的@Configuration註解使用Spring
- SpringBoot 註解呼叫Redis快取Spring BootRedis快取
- 【Spring 註解】@Configuration和@BeanSpringBean
- SpringBoot自動裝配原理之Configuration以及@Bean註解的使用Spring BootBean
- springboot:使用非同步註解@Async獲取執行結果的坑Spring Boot非同步
- 【Spring註解開發】元件註冊-使用@Configuration和@Bean給容器中註冊元件Spring元件Bean
- springboot註解方式使用redis快取Spring BootRedis快取
- Java註解詳解「註解專案實戰」Java
- 【SpringBoot實戰】核心配置和註解Spring Boot
- SpringBoot基於註解方式配置FilterSpring BootFilter
- spring配置redis註解快取SpringRedis快取
- SpringBoot註解Spring Boot
- Spring-@Configuration註解簡析Spring
- SpringBoot 中獲取專案的路徑和檔案流Spring Boot
- springboot的@ConditionalOnBean註解Spring BootBean
- 透過JPA註解獲取某個類主鍵欄位
- SpringBoot 註解@ConfiguretionPropertiesSpring Boot
- Springboot 常用註解Spring Boot
- java springboot 註解JavaSpring Boot
- 【SpringBoot系列】SpringBoot註解詳解Spring Boot
- 註解類
- SpringBoot註解使用redis做快取總結Spring BootRedis快取
- SpringBoot之日誌註解和快取優化Spring Boot快取優化
- Spring_Mybatis整合 註解配置類與xml配置檔案兩種方式分析及初始化IOC容器與監聽獲取取IOC容器SpringMyBatisXML
- java中SpringBoot定時器註解JavaSpring Boot定時器
- 商標使用中應注意哪些問題?註冊商標專用權如何獲得保護?
- phpstrom 註冊碼獲取PHP
- Springboot 獲取jar包中的檔案Spring BootJAR
- SpringBoot通過@ConfigurationProperties註解和@Value讀取資原始檔中的值Spring Boot