千家信息网

Feign中EnableFeignClients的作用是什么

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这期内容当中小编将会给大家带来有关Feign中EnableFeignClients的作用是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。springcloud-
千家信息网最后更新 2026年11月01日Feign中EnableFeignClients的作用是什么

这期内容当中小编将会给大家带来有关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实现。

图1

如下List-3,分俩个步骤,首先是registerDefaultConfiguration方法,将EnableFeignClients的defaultConfiguration注册到Spring容器中;之后是registerFeignClients方法将FeignClient注解的接口注册到Spring容器中。

List-3

@Overridepublic 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 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 basePackages;    Map 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 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 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 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的作用是什么了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

接口 方法 属性 注解 容器 作用 复杂 内容 所在 条件 类型 路径 分析 封装 有意思 专业 中小 内容丰富 参数 同时 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广东万易互联网科技有限公司惠州分公司 互联网电商科技 互联网科技垄断 美国互联网科技 深圳互联网络科技有限公司 安徽鑫晟辉互联网科技 小马过河互联网科技 无线互联网科技 互联网高科技企业 茂名市互联网科技产业园 东莞新华互联网科技学校 互联网第三次科技革命特征 互联网科技资金流入 信承诺互联网科技有限公司 艺电能源互联网科技有限公司招聘 互联网科技职业技能培训学校 盐城市攀科互联网科技有限公司 承德科技产业互联网平台 互联网科技创业计划的风险分析 宁波允成互联网科技有限公司 互联网科技资迅 科技类的互联网平台 四个字互联网科技公司取名 互联网科技生活的内容 中国的互联网科技企业的崛起 创业天下互联网科技有限公司 受益于互联网科技的高速发展 互联网营销推广黑科技 珠海东科互联网科技有限公司 互联网领先科技成果宣传视频
0