91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Feign中EnableFeignClients的作用是什么

發布時間:2021-08-03 11:34:42 來源:億速云 閱讀:787 作者:Leah 欄目:大數據

這期內容當中小編將會給大家帶來有關Feign中EnableFeignClients的作用是什么,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

    springcloud-openfeign-core-2.1.1.release.

    在springcloud中使用feign的時候,如下List-1,FeignClient的name是服務名稱,會自動從Eureka中獲取物理地址。

    List-1

@FeignClient(name="UserProvider")
public interface UserProvider {
...
}

    Springcloud中這個是如何實現的?

    這個要從@EnableFeignClients入手,如下List-2,Import注解引入了FeignClientsRegistrar——實現了ImportBeanDefinitionRegistrar接口,這樣springboot會處理這個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所示,FeignClientsRegistrar并沒有復雜的繼承關系,重點類看ImportBeanDefinitionRegistrar的registerBeanDefinitions實現。

      Feign中EnableFeignClients的作用是什么

                                                                                          圖1

    如下List-3,分倆個步驟,首先是registerDefaultConfiguration方法,將EnableFeignClients的defaultConfiguration注冊到Spring容器中;之后是registerFeignClients方法將FeignClient注解的接口注冊到Spring容器中。

    List-3

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
        BeanDefinitionRegistry registry) {
    registerDefaultConfiguration(metadata, registry);
    registerFeignClients(metadata, registry);
}

    來看registerDefaultConfiguration方法,如下List-4,

  1. 獲取EnableFeignClients的所有屬性,之后如果含有defaultConfiguration,則將defaultConfiguration注冊到Spring容器中

  2. 方法registerClientConfiguration中,用Builder模式,構造FeignClientSpecification類型的BeanDefinition。FeignClientSpecification實現了NamedContextFactory.Specification接口,屬性有個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方法中,實現則較為復雜,如下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. 1處獲取ClassPathScanner,用于掃描類路徑

  2. 2處獲取EnableFeignClients的所有屬性

  3. 3處構造一個AnnotationTypeFilter,構造方法參數是FeignClient,這個用于過濾出只含有FeignClient的類

  4. 獲得EnableFeignClients的clients屬性值,4處如果是空,則獲得EnableFeignClients所在的package路徑(如果沒有設置basePackageClasses)

  5. 5處,即EnableFeignClients的clients屬性不是空,則遍歷,放入集合中,同時獲取client所在的package路面,加入到basePacakges中;構造AbstractClassTestingTypeFilter,這是增加一個過濾條件,即標FeignClient注解的接口,必須在EnableFeignClients的clients中

  6. 遍歷basePackages,獲取每個package下的符合條件的類,得到對應的beanDefinition,6處得到FeignClient的configuration值,通過FeignClientSpecification其注冊到spring容器中,有意思的是這里檢查了FeignClient注解的類須是接口,不然會報錯。

  7. 7處將FeignClient注解的接口封裝到FeignClientFactoryBean中,FactoryBean大家懂的,Spring中接口都封裝到這個里面。

上述就是小編為大家分享的Feign中EnableFeignClients的作用是什么了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

资中县| 仪陇县| 卫辉市| 长岭县| 梅河口市| 巩义市| 海原县| 丰台区| 建瓯市| 东乌珠穆沁旗| 永平县| 灵石县| 泽普县| 刚察县| 黄梅县| 奉化市| 巴青县| 海盐县| 礼泉县| 襄汾县| 永兴县| 铜川市| 芜湖县| 苍梧县| 南宫市| 托克逊县| 洪湖市| 达州市| 新宾| 社会| 历史| 崇礼县| 阿勒泰市| 四子王旗| 宣武区| 札达县| 门源| 宁武县| 五寨县| 西乡县| 邵武市|