• OpenFeign源码1-环境搭建及核心类说明


    0. 环境

    • nacos版本:1.4.1
    • Spring Cloud : Hoxton.SR9(没用2020.0.2版本后面说明)
    • Spring Boot :2.4.4
    • Spring Cloud alibaba: 2.2.5.RELEASE
    • Spring Cloud openFeign 2.2.2.RELEASE

    测试代码:github.com/hsfxuebao/s…

    2020.0.X版本开始的OpenFeign底层不再使用Ribbon了

    1. 下载

    github地址:github.com/spring-clou…

    由于是maven工程,直接导入IDEA中就可以了

    2. 核心类介绍

    2.1 @EnableFeignClients

    1. // @EnableFeignClients注解用来启动FeignClient,以支持Feign。
    2. // 该注解可以通过配置,扫描指定位置的@FeignClient注解声明的Feign客户端接口
    3. @Retention(RetentionPolicy.RUNTIME)
    4. @Target(ElementType.TYPE)
    5. @Documented
    6. @Import(FeignClientsRegistrar.class)
    7. public @interface EnableFeignClients {
    8. // value和basePackage具有相同的功能,其中value是basePackage的别名
    9. // value和basePackage只能同时使用一个
    10. /**
    11. * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
    12. * declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
    13. * {@code @ComponentScan(basePackages="org.my.pkg")}.
    14. * @return the array of 'basePackages'.
    15. */
    16. // 为basePackages属性的别名,允许使用更简洁的书写方式。例如:@EnableFeignClients({"com.cd", "com.ad"})
    17. String[] value() default {};
    18. /**
    19. * Base packages to scan for annotated components.
    20. *

    21. * {@link #value()} is an alias for (and mutually exclusive with) this attribute.
    22. *

    23. * Use {@link #basePackageClasses()} for a type-safe alternative to String-based
    24. * package names.
    25. * @return the array of 'basePackages'.
    26. */
    27. // 设置自动扫描带有@FeignClient注解的基础包路径。例如 @EnableFeignClients(basePackages = {"com.cd", "com.ad"})
    28. String[] basePackages() default {};
    29. /**
    30. * Type-safe alternative to {@link #basePackages()} for specifying the packages to
    31. * scan for annotated components. The package of each class specified will be scanned.
    32. *

    33. * Consider creating a special no-op marker class or interface in each package that
    34. * serves no purpose other than being referenced by this attribute.
    35. * @return the array of 'basePackageClasses'.
    36. */
    37. // 该属性是basePackages属性的安全替代属性。该属性将扫描指定的每个类所在的包下面的所有被@FeignClient修饰的类;
    38. // 这需要考虑在每个包中创建一个特殊的标记类或接口,该类或接口除了被该属性引用外,没有其他用途
    39. Class<?>[] basePackageClasses() default {};
    40. /**
    41. * A custom @Configuration for all feign clients. Can contain override
    42. * @Bean definition for the pieces that make up the client, for instance
    43. * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
    44. *
    45. * @see FeignClientsConfiguration for the defaults
    46. * @return list of default configurations
    47. */
    48. // 该属性用来自定义所有Feign客户端的配置,使用@Configuration进行配置。
    49. // 当然也可以为某一个Feign客户端进行配置。具体配置方法见@FeignClient的configuration属性。
    50. Class<?>[] defaultConfiguration() default {};
    51. /**
    52. * List of classes annotated with @FeignClient. If not empty, disables classpath
    53. * scanning.
    54. * @return list of FeignClient classes
    55. */
    56. // 设置由@FeignClient注解修饰的类列表。如果clients不是空数组,则不通过类路径自动扫描功能来加载FeignClient
    57. // 例如 @EnableFeignClients(clients = {SchedualService.class})
    58. // 上面代码中引入FeignClient客户端SchedualService,且也只引入该FeignClient客户端。
    59. Class<?>[] clients() default {};
    60. }
    61. 复制代码

    2.2 @FeignClient

    1. @Target(ElementType.TYPE)
    2. @Retention(RetentionPolicy.RUNTIME)
    3. @Documented
    4. public @interface FeignClient {
    5. // name 和 value 两个属性等价,至少要配置一个
    6. /**
    7. * The name of the service with optional protocol prefix. Synonym for {@link #name()
    8. * name}. A name must be specified for all clients, whether or not a url is provided.
    9. * Can be specified as property key, eg: ${propertyKey}.
    10. * @return the name of the service with optional protocol prefix
    11. */
    12. @AliasFor("name")
    13. String value() default "";
    14. /**
    15. * The service id with optional protocol prefix. Synonym for {@link #value() value}.
    16. * @deprecated use {@link #name() name} instead
    17. * @return the service id with optional protocol prefix
    18. */
    19. @Deprecated
    20. String serviceId() default "";
    21. /**
    22. * This will be used as the bean name instead of name if present, but will not be used
    23. * as a service id.
    24. * @return bean name instead of name if present
    25. */
    26. // 别名,假设一个User服务有两个FeignClient,都需要调用Product服务, 因为name属性值一样,所以需要通过配置contextId来区分,否则启动项目时会报错
    27. String contextId() default "";
    28. /**
    29. * @return The service id with optional protocol prefix. Synonym for {@link #value()
    30. * value}.
    31. */
    32. @AliasFor("value")
    33. String name() default "";
    34. /**
    35. * @return the @Qualifier value for the feign client.
    36. */
    37. // 返回默认值=contextId+“FeignClient”。
    38. String qualifier() default "";
    39. /**
    40. * @return an absolute URL or resolvable hostname (the protocol is optional).
    41. */
    42. // 请求地址, 没配置的话, 会把name/value的属性值当成服务名进行调用, 配置的话则使用url的值
    43. String url() default "";
    44. /**
    45. * @return whether 404s should be decoded instead of throwing FeignExceptions
    46. */
    47. // 当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
    48. boolean decode404() default false;
    49. /**
    50. * A custom configuration class for the feign client. Can contain override
    51. * @Bean definition for the pieces that make up the client, for instance
    52. * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
    53. *
    54. * @see FeignClientsConfiguration for the defaults
    55. * @return list of configurations for feign client
    56. */
    57. // Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
    58. Class<?>[] configuration() default {};
    59. /**
    60. * Fallback class for the specified Feign client interface. The fallback class must
    61. * implement the interface annotated by this annotation and be a valid spring bean.
    62. * @return fallback class for the specified Feign client interface
    63. */
    64. // 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
    65. Class<?> fallback() default void.class;
    66. /**
    67. * Define a fallback factory for the specified Feign client interface. The fallback
    68. * factory must produce instances of fallback classes that implement the interface
    69. * annotated by {@link FeignClient}. The fallback factory must be a valid spring bean.
    70. *
    71. * @see feign.hystrix.FallbackFactory for details.
    72. * @return fallback factory for the specified Feign client interface
    73. */
    74. // 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
    75. Class<?> fallbackFactory() default void.class;
    76. /**
    77. * @return path prefix to be used by all method-level mappings. Can be used with or
    78. * without @RibbonClient.
    79. */
    80. // 所有方法级映射使用的路径前缀
    81. String path() default "";
    82. /**
    83. * @return whether to mark the feign proxy as a primary bean. Defaults to true.
    84. */
    85. // 是否将外部代理标记为主bean。默认为true。
    86. boolean primary() default true;
    87. }
    88. 复制代码

    2.3 FeignClientSpecification

    FeignClientSpecification 是 Feign Client 生成规范:

    2.4 FeignContext

    FeignContext 是一个为 Feign Client 创建所准备的上下文对象

    1. // FeignContext 是一个为 Feign Client 创建所准备的上下文对象
    2. public class FeignContext extends NamedContextFactory {
    3. public FeignContext() {
    4. super(FeignClientsConfiguration.class, "feign", "feign.client.name");
    5. }
    6. }
    7. 复制代码

    其父类为:

    1. public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
    2. implements DisposableBean, ApplicationContextAware {
    3. private final String propertySourceName;
    4. private final String propertyName;
    5. // todo 该 map 的 key 为 FeignClient 的名称(其所要调用的微服务名称), value 是组装这个
    6. // FeignClient 所必须的组件所在的 Spring 子容器
    7. private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
    8. // 这个map中存放的是@EnableFeignClients与@FeignClient两个注解中的configuration属性值。
    9. // 这个属性值只有两类:
    10. // 第一类只有一个,其 key 为字符串 default + 当前启动类的全限定性类名 ,例如:
    11. // default.com.abc.ConsumerFeign8080, value 为@EnableFeignClients 的 defaultConfiguration属性值
    12. // 第二类有多个,其 key 为当前@FeignClient 的名称, value 为这个注解的 configuration 属性值
    13. private Map<String, C> configurations = new ConcurrentHashMap<>();
    14. private ApplicationContext parent;
    15. private Class<?> defaultConfigType;
    16. public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName,
    17. String propertyName) {
    18. this.defaultConfigType = defaultConfigType;
    19. this.propertySourceName = propertySourceName;
    20. this.propertyName = propertyName;
    21. }
  • 相关阅读:
    SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.7 memcached 下载与安装
    知名工业企业代表团赴实在智能交流,共同推动企业数字化转型
    CentOS 7下yum安装GitLab CE
    文章主要内容提取软件[基于NLP技术]
    GPT引领前沿与应用突破之GPT4科研实践技术与AI绘图
    6个小技巧,帮助职场新人培养项目管理能力
    盒子模型的基础
    pytorch初学笔记(七):神经网络基本骨架 torch.nn.Module
    第3章 处理机调度与死锁
    谁在成为产业供应链的“新发动机”?
  • 原文地址:https://blog.csdn.net/BASK2311/article/details/127959279