SOFABoot原始碼解析之啟動原理(2)-原始碼解析
1. private voidprocessImports(ConfigurationClass configClass, SourceClass currentSourceClass,
2. Collection<SourceClass>importCandidates, boolean checkForCircularImports) throws IOException {
3. 4. ……略
5. if(checkForCircularImports && isChainedImportOnStack(configClass)) {
6. ……略
7. }
8. else{
9. this.importStack.push(configClass);
10. try{
11. for (SourceClass candidate : importCandidates){
12. if(candidate.isAssignable(ImportSelector.class)) {
13. //Candidate class is an ImportSelector -> delegate to it to determine imports
14. Class<?>candidateClass = candidate.loadClass();
15. ImportSelectorselector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
16. ParserStrategyUtils.invokeAwareMethods(
17. selector,this.environment, this.resourceLoader, this.registry);
18. if(this.deferredImportSelectors != null && selector instanceofDeferredImportSelector) {
19. this.deferredImportSelectors.add(
20. newDeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
21. }
22. else{
23. String[]importClassNames = selector.selectImports(currentSourceClass.getMetadata());
24. Collection<SourceClass>importSourceClasses = asSourceClasses(importClassNames);
25. processImports(configClass,currentSourceClass, importSourceClasses, false);
26. }
27. }
28. elseif (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
29. //Candidate class is an ImportBeanDefinitionRegistrar ->
30. //delegate to it to register additional bean definitions
31. Class<?>candidateClass = candidate.loadClass();
32. ImportBeanDefinitionRegistrarregistrar =
33. BeanUtils.instantiateClass(candidateClass,ImportBeanDefinitionRegistrar.class);
34. ParserStrategyUtils.invokeAwareMethods(
35. registrar,this.environment, this.resourceLoader, this.registry);
36. configClass.addImportBeanDefinitionRegistrar(registrar,currentSourceClass.getMetadata());
37. }
38. else{
39. //Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
40. //process it as an @Configuration class
41. this.importStack.registerImport(
42. currentSourceClass.getMetadata(),candidate.getMetadata().getClassName());
43. processConfigurationClass(candidate.asConfigClass(configClass));
44. }
45. }
46. }
47. catch(BeanDefinitionStoreException ex) {
48. throwex;
49. }
50. catch(Throwable ex) {
51. ……略
52. }
53. finally{
54. this.importStack.pop();
55. }
56. }
57. }
processImports方法主要邏輯:
1) 如果匯入的配置類實現了DeferredImportSelector介面,則建立DeferredImportSelectorHolder例項,並置入deferredImportSelectors連結串列中,待上述processConfigBeanDefinitions方法下一個do{*}while(*)迴圈中處理。
2) 如果匯入的配置類實現了ImportSelector介面,則呼叫該類的selectImports方法匯入新的@Configuration配置類,並巢狀呼叫processImports方法,處理匯入的@Configuration配置類。
3) 如果匯入的配置類實現了ImportBeanDefinitionRegistrar介面,則建立ImportBeanDefinitionRegistrar例項,並在處理@Configuration配置類過程中,委託該例項註冊額外的BeanDefinition。
4) 如果以上都不是,則匯入的配置類為基本的@Configuration配置類,直接呼叫processConfigurationClass處理,最終具體解析操作在doProcessConfigurationClass方法中實現。
1. protected final SourceClassdoProcessConfigurationClass(ConfigurationClass configClass, SourceClasssourceClass) throws IOException {
2. //Recursively process any member (nested) classes first
3. processMemberClasses(configClass,sourceClass);
4. 5. //處理@PropertySource註解
6. for(AnnotationAttributes propertySource :AnnotationConfigUtils.attributesForRepeatable(
7. sourceClass.getMetadata(),PropertySources.class, org.springframework.context.annotation.PropertySource.class)){
8. if(this.environment instanceof ConfigurableEnvironment) {
9. processPropertySource(propertySource);
10. }
11. else{
12. logger.warn("[email protected] annotation on [" + sourceClass.getMetadata().getClassName()+
13. "].Reason: Environment must implement ConfigurableEnvironment");
14. }
15. }
16. 17. // 處理@ComponentScan註解
18. Set<AnnotationAttributes>componentScans = AnnotationConfigUtils.attributesForRepeatable(
19. sourceClass.getMetadata(),ComponentScans.class, ComponentScan.class);
20. if(!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(),ConfigurationPhase.REGISTER_BEAN)) {
21. for(AnnotationAttributes componentScan : componentScans) {
22. //The config class is annotated with @ComponentScan -> perform the scanimmediately
23. Set<BeanDefinitionHolder>scannedBeanDefinitions =
24. this.componentScanParser.parse(componentScan,sourceClass.getMetadata().getClassName());
25. //Check the set of scanned definitions for any further config classes and parserecursively if necessary
26. for(BeanDefinitionHolder holder : scannedBeanDefinitions) {
27. if(ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(),this.metadataReaderFactory)) {
28. parse(holder.getBeanDefinition().getBeanClassName(),holder.getBeanName());
29. }
30. }
31. }
32. }
33. 34. //處理@Import註解
35. processImports(configClass, sourceClass,getImports(sourceClass), true);
36. 37. //處理@ImportResource註解
38. if(sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
39. AnnotationAttributesimportResource =
40. AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),ImportResource.class);
41. String[]resources = importResource.getStringArray("locations");
42. Class<?extends BeanDefinitionReader> readerClass =importResource.getClass("reader");
43. for(String resource : resources) {
44. StringresolvedResource = this.environment.resolveRequiredPlaceholders(resource);
45. configClass.addImportedResource(resolvedResource,readerClass);
46. }
47. }
48. 49. //處理@Bean方法
50. Set<MethodMetadata>beanMethods =sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());
51. for(MethodMetadata methodMetadata : beanMethods) {
52. configClass.addBeanMethod(newBeanMethod(methodMetadata, configClass));
53. }
54. 55. ……略
56. 57. //No superclass -> processing is complete
58. returnnull;
59. }
針對每個@Configuration配置類,依次處理@Configuration配置類中的@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean註解,主要解析過程如下:
1) @PropertySource處理過程:呼叫processPropertySource方法處理屬性源,在此不詳述;
2) @ComponentScan處理過程:解析@Configuration配置類中@ComponentScan、@ComponentScans註解,並根據設定的basePackages掃描指定的包路徑,並載入、註冊所有帶有@Component註解及@Component衍生註解(如@Controller、@Service、@Repository、@Configuration等)Java類的Bean定義到Spring應用上下文;
3) @Import處理過程:參考上述processImports方法描述。需要注意,在處理某個配置類的@Import註解過程中,如果發現@Import匯入的類實現了DeferredImportSelector介面,則建立DeferredImportSelectorHolder例項,並置入deferredImportSelectors連結串列中,待下一次迴圈處理。以此類推,直至所有的@Configuration配置類載入完畢。例如:在處理SofaBootRpcDemoApplication的@Import註解時,由於在SofaBootRpcDemoApplication類@SpringBootApplication註解中引用了@EnableAutoConfiguration註解,而它又引用了@Import(value={EnableAutoConfigurationImportSelector.class})。由於EnableAutoConfigurationImportSelector實現了DeferredImportSelector介面,所以在此建立DeferredImportSelectorHolder例項,並置入deferredImportSelectors連結串列中,待所有@Configuration註解類解析完成以後再處理。
4) @ImportResource處理過程:解析locations屬性,並依次獲取locations指定目錄下Spring XML配置檔案,設定configClass類的importedResource屬性;
5) @Bean處理過程:讀取@Configuration配置類中@Bean註解的方法,並增加到configClass的beanMethod集合。
至此,處理完現有candidates中所有@Configuration配置類。
在回看一下processConfigBeanDefinitions方法:相關推薦
SOFABoot原始碼解析之啟動原理(2)-原始碼解析
1. private voidprocessImports(ConfigurationClass configClass, SourceClass currentSourceClass,2. Collection<SourceClass>importCandidates, b
SOFABoot原始碼解析之啟動原理(1)-註解分析
一 、概述 SOFABoot是螞蟻金服開源的基於 Spring Boot 的研發框架,它在Spring Boot 的基礎上,提供了諸如 Readiness Check,類隔離,日誌空間隔離等等能力。在增強了 Spring Boot 的同時,SOFABoot 提供
elasticsearch原始碼分析之啟動過程(二)
最近開始廣泛的使用elasticsearch,也開始寫一些java程式碼了,為了提高java程式碼能力,也為了更加深入一點了解elasticsearch的內部運作機制,所以開始看一些elasticsearch的原始碼了。對於這種廣受追捧的開源專案,細細品讀一定會受益匪淺,
併發程式設計(十二)—— Java 執行緒池 實現原理與原始碼深度解析 之submit方法 (二)
在上一篇《併發程式設計(十一)—— Java 執行緒池 實現原理與原始碼深度解析(一)》中提到了執行緒池ThreadPoolExecutor的原理以及它的execute方法。這篇文章是接著上一篇文章寫的,如果你沒有閱讀上一篇文章,建議你去讀讀。本文解析ThreadPoolExecutor#submit。
Android View原理解析之測量流程(measure)
提示:本文的原始碼均取自Android 7.0(API 24) 前言 自定義View是Android進階路線上必須攻克的難題,而在這之前就應該先對View的工作原理有一個系統的理解。本系列將分為4篇部落格進行講解,本文主要對View的測量流程進行講解。相關內容如
Android View原理解析之佈局流程(layout)
提示:本文的原始碼均取自Android 7.0(API 24) 前言 自定義View是Android進階路線上必須攻克的難題,而在這之前就應該先對View的工作原理有一個系統的理解。本系列將分為4篇部落格進行講解,本文主要對View的佈局流程進行講解。相關內容如
mybatis原始碼解析之Configuration載入(一)
概要 上一篇,我們主要搭建了一個簡單的環境,這邊我們主要來分析下mybatis是如何來載入它的配置檔案Configuration.xml的。 分析 1 public class App { 2 public static void main(String[] args) { 3
mybatis原始碼解析之Configuration載入(二)
概述 上一篇我們講了configuation.xml中幾個標籤的解析,例如<properties>,<typeAlises>,<settings>等,今天我們來介紹剩下的兩個比較重要的標籤之一,<environments>,這個標籤主要用於我們訪問資料庫的配置
LDA原理(2)知識儲備之貝葉斯派和概率派
介紹貝葉斯派和概率派 概率派認為要推斷的引數是固定的值,雖然概率是未知的,但是一定是固定的值,同時樣本是隨機的,既然這樣,他們的側重點就是研究樣本空間,比如我們不知道拋硬幣正面朝上的概率,那概率派的思路就是做很多次的拋硬幣的實驗,試驗次數越多,越能逼近概率
Android4.4.2原始碼分析之WiFi模組(一)
已經寫了幾篇關於Android原始碼的,原始碼程式碼量太大,所以如果想分析某個模組可能不知如何下手,說一下思路 1,分析原始碼英文閱讀能力要夠,想要分析某個模組一般找模組對應的英文,就是模組 2,找到之後首先檢視清單配置檔案Androidmani.fest,找到程式主介面activity 3,通過檢視配置檔
Codis原始碼解析——處理slot操作(2)
這一篇我們把處理slot操作的機制講完。還剩最後兩個部分。一個是fillSlot,一個是每一個槽具體的處理方式。 本例中有兩個group,將之前auto-rebalance過的slot(0-511屬於group1,512-1023屬於group2) 現在
Android4.4.2原始碼分析之WiFi模組(二)
接著上一篇繼續對WiFi原始碼的分析 onResume方法中 6>,首先是呼叫WiFiEnabler的resume方法對switch進行管理 接下來註冊廣播 getActivity().registerReceiver(mReceiver, mFilter);
ConcurrentHashMap原理(2)之用分離鎖實現多個執行緒間的併發寫操作
ConcurrentHashMap 類 ConcurrentHashMap 在預設併發級別會建立包含 16 個 Segment 物件的陣列。每個 Segment 的成員物件 table 包含若干個散列表的桶。每個桶是由 HashEntry 連結起來的一個連結串列。如果鍵能均
spring原始碼解析之IOC容器(一)
學習優秀框架的原始碼,是提升個人技術水平必不可少的一個環節。如果只是停留在知道怎麼用,但是不懂其中的來龍去脈,在技術的道路上註定走不長遠。最近,學習了一段時間的spring原始碼,現在整理出來,以便日後溫故知新。 IOC容器是spring最核心的模組之一,是整個spring體系的基石,spring其
spring原始碼解析之IOC容器(二)------載入和註冊
上一篇跟蹤了IOC容器對配置檔案的定位,現在我們繼續跟蹤程式碼,看看IOC容器是怎麼載入和註冊配置檔案中的資訊的。開始之前,首先我們先來了解一下IOC容器所使用的資料結構-------BeanDefinition,它是一個上層介面,有很多實現類,分別對應不同的資料載體。我們平時開發的時候,也會定義很多po
spring原始碼解析之IOC容器(三)——依賴注入
上一篇主要是跟蹤了IOC容器對bean標籤進行解析之後存入Map中的過程,這些bean只是以BeanDefinition為載體單純的儲存起來了,並沒有轉換成一個個的物件,今天繼續進行跟蹤,看一看IOC容器是怎樣例項化物件的。 我們都使用過以下程式碼: 1 FileSystemXmlApplicati
Spring原始碼解析之基礎應用(二)
方法注入 在spring容器中,大部分bean的作用域(scope)是單例(singleton)的,少部分bean的作用域是原型(prototype),如果一個bean的作用域是原型,我們A bean的作用域是原型,B bean中以@Autowired的方式注入A,那麼B在A中依舊是單例。我們可以讓B類實現A
Spring原始碼解析之基礎應用(三)
組合Java配置 在XML中,我們可以使用<import/>標籤,在一個XML檔案中引入另一個XML檔案,在Java類中,我們同樣可以在一個配置類中用@Import引入另一個配置類,被引入的配置類中的@Bean也會載入到spring容器。程式碼如下: @Configuration public
斷點 相關技術與原理(2)
def pan 保存 ollydbg php class 工具 code http 繼續對OD的斷點技術做個筆記。 1、硬件斷點: Intel CPU中有8個調試寄存器(Debug Register)DR0 — DR7,當中DR0 — DR3用於設置硬件斷點地址,D
HectorSLAM論文解析?代碼重寫(2)
開始 機器人 狀態 核心 基本上 測試數據 logs grid 機器 這篇文章為HectorSLAM系列的以下部分 HectorSLAM的整體邏輯 激光匹配 地圖構造 地圖更新 500行代碼重寫一個LidarSLAM 測試數據的準備,和測試數據讀取模塊的編寫