源碼解析 - 註冊bean
從@EnableFeignClients
開始分析。
@EnableFeignClients
的作用是掃描標註@FeignClient
註解的所有接口。
現在重點關注下FeignClientRegistrar這個類。
它重寫了ImportBeanDefinitionRegistrar
接口的如下方法:
這個方法用來在上下文中註冊BeanDefinitions。
先來看下第一部分的registerDefaultConfiguration(...)
方法。
首先是獲取@EnableFeignClients
註解的屬性以及屬性值。
如果有設置defaultConfiguration屬性值,執行registerClientConfiguration(…)方法。
首先是構造了一個BeanDefinitionBuilder實例。
現在來看下如何構造的。
實際上就是GenericBeanDefinition調用setBeanClass(Class<?> beanClass)方法。這裏的方法的參數beanClass就是FeignClientSpefication.class。
接下來看:
實際上是調用ConstructorArgumentValues的addIndexedArgumentValue(…)方法。它會重寫原有的屬性值
第一個參數是構造器中的參數下標,第二個參數是參數對應的值。
最後還剩下,如下方法:
註冊BeanDefinition。
這個是屬於Spring框架的在上下文中註冊bean方法。(這裏不展開解析。)
第二部分分析下registerFeignClients(…)方法
構造一個ClassPathScanningCandidateComponentProvider實例。
ClassPathScanningCandidateComponentProvider scanner = getScanner();
重寫了isCandidateComponent方法。對於bean定義中的元數據屬於independent,但是不是個註解,就會符合候選的條件。
isIndepent方法,定義如下:
設置ResourceLoader。
scanner.setResourceLoader(this.resourceLoader);
獲取@EnableFeignCients註解的所有屬性以及相關屬性值。
Map<String, Object> attrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName());
構造了一個AnnotationTypeFilter實例
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
FeignClient.class);
而AnnotationTypeFilter,定義如下:
獲取@EnableFeignClients註解的clients屬性值
final Class<?>[] clients = attrs == null ? null
: (Class<?>[]) attrs.get("clients");
這個屬性在@EnableFeignClients註解定義如下:
如果沒有設置clients屬性,在TypeFilter列表中添加指定的AnnotationTypeFilter
獲取@EnableFeignClients註解中設置的指定包
再看下@EnableFeignClients註解的value、basePackages、basePackageClasses屬性值。
如果有設置clients屬性,執行如下
然後會遍歷basePackages。如下:
要求@FeignClient註解標註在接口上。
獲取@FeignClient註解的contextId、value、name、serviceId屬性作爲指定的名字
註冊@FeignClient註解指定的配置類
registerClientConfiguration(registry, name,
attributes.get("configuration"));
方法具體的處理,上面有分析。這裏不再重複。
註冊標註@FeignClient的接口
registerFeignClient(registry, annotationMetadata, attributes);
構造一個BeanDefinitionHolder實例進行註冊
除了註冊bean定義之外,還會註冊別名