這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)Feign中EnableFeignClients的作用是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
成都創(chuàng)新互聯(lián)公司基于成都重慶香港及美國(guó)等地區(qū)分布式IDC機(jī)房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動(dòng)大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)服務(wù)器托管報(bào)價(jià),主機(jī)托管價(jià)格性價(jià)比高,為金融證券行業(yè)眉山聯(lián)通機(jī)房,ai人工智能服務(wù)器托管提供bgp線路100M獨(dú)享,G口帶寬及機(jī)柜租用的專業(yè)成都idc公司。
springcloud-openfeign-core-2.1.1.release.
在springcloud中使用feign的時(shí)候,如下List-1,F(xiàn)eignClient的name是服務(wù)名稱,會(huì)自動(dòng)從Eureka中獲取物理地址。
List-1
@FeignClient(name="UserProvider") public interface UserProvider { ... }
Springcloud中這個(gè)是如何實(shí)現(xiàn)的?
這個(gè)要從@EnableFeignClients入手,如下List-2,Import注解引入了FeignClientsRegistrar——實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口,這樣springboot會(huì)處理這個(gè)FeignClientsRegistrar。
List-2
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(FeignClientsRegistrar.class) public @interface EnableFeignClients { String[] value() default {}; String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<?>[] defaultConfiguration() default {}; Class<?>[] clients() default {}; }
如下圖1所示,F(xiàn)eignClientsRegistrar并沒有復(fù)雜的繼承關(guān)系,重點(diǎn)類看ImportBeanDefinitionRegistrar的registerBeanDefinitions實(shí)現(xiàn)。
圖1
如下List-3,分倆個(gè)步驟,首先是registerDefaultConfiguration方法,將EnableFeignClients的defaultConfiguration注冊(cè)到Spring容器中;之后是registerFeignClients方法將FeignClient注解的接口注冊(cè)到Spring容器中。
List-3
@Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { registerDefaultConfiguration(metadata, registry); registerFeignClients(metadata, registry); }
來看registerDefaultConfiguration方法,如下List-4,
獲取EnableFeignClients的所有屬性,之后如果含有defaultConfiguration,則將defaultConfiguration注冊(cè)到Spring容器中
方法registerClientConfiguration中,用Builder模式,構(gòu)造FeignClientSpecification類型的BeanDefinition。FeignClientSpecification實(shí)現(xiàn)了NamedContextFactory.Specification接口,屬性有個(gè)name和Class<?>類型的configuration。
List-4
private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { Map<String, Object> defaultAttrs = metadata .getAnnotationAttributes(EnableFeignClients.class.getName(), true); if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) { String name; if (metadata.hasEnclosingClass()) { name = "default." + metadata.getEnclosingClassName(); } else { name = "default." + metadata.getClassName(); } registerClientConfiguration(registry, name, defaultAttrs.get("defaultConfiguration")); } } private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) { BeanDefinitionBuilder builder = BeanDefinitionBuilder .genericBeanDefinition(FeignClientSpecification.class); builder.addConstructorArgValue(name); builder.addConstructorArgValue(configuration); registry.registerBeanDefinition( name + "." + FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition()); }
registerFeignClients方法中,實(shí)現(xiàn)則較為復(fù)雜,如下List-5
List-5
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { ClassPathScanningCandidateComponentProvider scanner = getScanner();//1 scanner.setResourceLoader(this.resourceLoader); Set<String> basePackages; Map<String, Object> attrs = metadata .getAnnotationAttributes(EnableFeignClients.class.getName());//2 AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter( FeignClient.class);//3 final Class<?>[] clients = attrs == null ? null : (Class<?>[]) attrs.get("clients"); if (clients == null || clients.length == 0) {//4 scanner.addIncludeFilter(annotationTypeFilter); basePackages = getBasePackages(metadata); } else {//5 final Set<String> clientClasses = new HashSet<>(); basePackages = new HashSet<>(); for (Class<?> clazz : clients) { basePackages.add(ClassUtils.getPackageName(clazz)); clientClasses.add(clazz.getCanonicalName()); } AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() { @Override protected boolean match(ClassMetadata metadata) { String cleaned = metadata.getClassName().replaceAll("\\$", "."); return clientClasses.contains(cleaned); } }; scanner.addIncludeFilter( new AllTypeFilter(Arrays.asList(filter, annotationTypeFilter))); } for (String basePackage : basePackages) { Set<BeanDefinition> candidateComponents = scanner .findCandidateComponents(basePackage); for (BeanDefinition candidateComponent : candidateComponents) { if (candidateComponent instanceof AnnotatedBeanDefinition) { // verify annotated class is an interface AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent; AnnotationMetadata annotationMetadata = beanDefinition.getMetadata(); Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface"); Map<String, Object> attributes = annotationMetadata .getAnnotationAttributes( FeignClient.class.getCanonicalName()); String name = getClientName(attributes); registerClientConfiguration(registry, name, attributes.get("configuration"));//6 registerFeignClient(registry, annotationMetadata, attributes);//7 } } } }
1處獲取ClassPathScanner,用于掃描類路徑
2處獲取EnableFeignClients的所有屬性
3處構(gòu)造一個(gè)AnnotationTypeFilter,構(gòu)造方法參數(shù)是FeignClient,這個(gè)用于過濾出只含有FeignClient的類
獲得EnableFeignClients的clients屬性值,4處如果是空,則獲得EnableFeignClients所在的package路徑(如果沒有設(shè)置basePackageClasses)
5處,即EnableFeignClients的clients屬性不是空,則遍歷,放入集合中,同時(shí)獲取client所在的package路面,加入到basePacakges中;構(gòu)造AbstractClassTestingTypeFilter,這是增加一個(gè)過濾條件,即標(biāo)FeignClient注解的接口,必須在EnableFeignClients的clients中
遍歷basePackages,獲取每個(gè)package下的符合條件的類,得到對(duì)應(yīng)的beanDefinition,6處得到FeignClient的configuration值,通過FeignClientSpecification其注冊(cè)到spring容器中,有意思的是這里檢查了FeignClient注解的類須是接口,不然會(huì)報(bào)錯(cuò)。
7處將FeignClient注解的接口封裝到FeignClientFactoryBean中,F(xiàn)actoryBean大家懂的,Spring中接口都封裝到這個(gè)里面。
上述就是小編為大家分享的Feign中EnableFeignClients的作用是什么了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
新聞標(biāo)題:Feign中EnableFeignClients的作用是什么
鏈接地址:http://aaarwkj.com/article38/jjgjsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、用戶體驗(yàn)、服務(wù)器托管、網(wǎng)頁(yè)設(shè)計(jì)公司、標(biāo)簽優(yōu)化、Google
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)