没用2020.0.2版本后面说明)
2020.0.X版本开始的OpenFeign底层不再使用Ribbon了
github地址:github.com/spring-clou…

由于是maven工程,直接导入IDEA中就可以了
- // @EnableFeignClients注解用来启动FeignClient,以支持Feign。
- // 该注解可以通过配置,扫描指定位置的@FeignClient注解声明的Feign客户端接口
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- @Documented
- @Import(FeignClientsRegistrar.class)
- public @interface EnableFeignClients {
-
- // value和basePackage具有相同的功能,其中value是basePackage的别名
- // value和basePackage只能同时使用一个
- /**
- * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
- * declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
- * {@code @ComponentScan(basePackages="org.my.pkg")}.
- * @return the array of 'basePackages'.
- */
- // 为basePackages属性的别名,允许使用更简洁的书写方式。例如:@EnableFeignClients({"com.cd", "com.ad"})
- String[] value() default {};
-
- /**
- * Base packages to scan for annotated components.
- *
- * {@link #value()} is an alias for (and mutually exclusive with) this attribute.
- *
- * Use {@link #basePackageClasses()} for a type-safe alternative to String-based
- * package names.
- * @return the array of 'basePackages'.
- */
- // 设置自动扫描带有@FeignClient注解的基础包路径。例如 @EnableFeignClients(basePackages = {"com.cd", "com.ad"})
- String[] basePackages() default {};
-
- /**
- * Type-safe alternative to {@link #basePackages()} for specifying the packages to
- * scan for annotated components. The package of each class specified will be scanned.
- *
- * Consider creating a special no-op marker class or interface in each package that
- * serves no purpose other than being referenced by this attribute.
- * @return the array of 'basePackageClasses'.
- */
- // 该属性是basePackages属性的安全替代属性。该属性将扫描指定的每个类所在的包下面的所有被@FeignClient修饰的类;
- // 这需要考虑在每个包中创建一个特殊的标记类或接口,该类或接口除了被该属性引用外,没有其他用途
- Class<?>[] basePackageClasses() default {};
-
- /**
- * A custom
@Configuration for all feign clients. Can contain override - *
@Bean definition for the pieces that make up the client, for instance - * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
- *
- * @see FeignClientsConfiguration for the defaults
- * @return list of default configurations
- */
- // 该属性用来自定义所有Feign客户端的配置,使用@Configuration进行配置。
- // 当然也可以为某一个Feign客户端进行配置。具体配置方法见@FeignClient的configuration属性。
- Class<?>[] defaultConfiguration() default {};
-
- /**
- * List of classes annotated with @FeignClient. If not empty, disables classpath
- * scanning.
- * @return list of FeignClient classes
- */
- // 设置由@FeignClient注解修饰的类列表。如果clients不是空数组,则不通过类路径自动扫描功能来加载FeignClient
- // 例如 @EnableFeignClients(clients = {SchedualService.class})
- // 上面代码中引入FeignClient客户端SchedualService,且也只引入该FeignClient客户端。
- Class<?>[] clients() default {};
-
- }
- 复制代码
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface FeignClient {
-
- // name 和 value 两个属性等价,至少要配置一个
- /**
- * The name of the service with optional protocol prefix. Synonym for {@link #name()
- * name}. A name must be specified for all clients, whether or not a url is provided.
- * Can be specified as property key, eg: ${propertyKey}.
- * @return the name of the service with optional protocol prefix
- */
- @AliasFor("name")
- String value() default "";
-
- /**
- * The service id with optional protocol prefix. Synonym for {@link #value() value}.
- * @deprecated use {@link #name() name} instead
- * @return the service id with optional protocol prefix
- */
- @Deprecated
- String serviceId() default "";
-
- /**
- * This will be used as the bean name instead of name if present, but will not be used
- * as a service id.
- * @return bean name instead of name if present
- */
- // 别名,假设一个User服务有两个FeignClient,都需要调用Product服务, 因为name属性值一样,所以需要通过配置contextId来区分,否则启动项目时会报错
- String contextId() default "";
-
- /**
- * @return The service id with optional protocol prefix. Synonym for {@link #value()
- * value}.
- */
- @AliasFor("value")
- String name() default "";
-
- /**
- * @return the
@Qualifier value for the feign client. - */
- // 返回默认值=contextId+“FeignClient”。
- String qualifier() default "";
-
- /**
- * @return an absolute URL or resolvable hostname (the protocol is optional).
- */
- // 请求地址, 没配置的话, 会把name/value的属性值当成服务名进行调用, 配置的话则使用url的值
- String url() default "";
-
- /**
- * @return whether 404s should be decoded instead of throwing FeignExceptions
- */
- // 当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
- boolean decode404() default false;
-
- /**
- * A custom configuration class for the feign client. Can contain override
- *
@Bean definition for the pieces that make up the client, for instance - * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
- *
- * @see FeignClientsConfiguration for the defaults
- * @return list of configurations for feign client
- */
- // Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
- Class<?>[] configuration() default {};
-
- /**
- * Fallback class for the specified Feign client interface. The fallback class must
- * implement the interface annotated by this annotation and be a valid spring bean.
- * @return fallback class for the specified Feign client interface
- */
- // 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
- Class<?> fallback() default void.class;
-
- /**
- * Define a fallback factory for the specified Feign client interface. The fallback
- * factory must produce instances of fallback classes that implement the interface
- * annotated by {@link FeignClient}. The fallback factory must be a valid spring bean.
- *
- * @see feign.hystrix.FallbackFactory for details.
- * @return fallback factory for the specified Feign client interface
- */
- // 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
- Class<?> fallbackFactory() default void.class;
-
- /**
- * @return path prefix to be used by all method-level mappings. Can be used with or
- * without
@RibbonClient. - */
- // 所有方法级映射使用的路径前缀
- String path() default "";
-
- /**
- * @return whether to mark the feign proxy as a primary bean. Defaults to true.
- */
- // 是否将外部代理标记为主bean。默认为true。
- boolean primary() default true;
-
- }
- 复制代码
FeignClientSpecification 是 Feign Client 生成规范:

FeignContext 是一个为 Feign Client 创建所准备的上下文对象
- // FeignContext 是一个为 Feign Client 创建所准备的上下文对象
- public class FeignContext extends NamedContextFactory
{ -
- public FeignContext() {
- super(FeignClientsConfiguration.class, "feign", "feign.client.name");
- }
-
- }
- 复制代码
其父类为:
- public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
- implements DisposableBean, ApplicationContextAware {
-
- private final String propertySourceName;
-
- private final String propertyName;
-
- // todo 该 map 的 key 为 FeignClient 的名称(其所要调用的微服务名称), value 是组装这个
- // FeignClient 所必须的组件所在的 Spring 子容器
- private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
-
- // 这个map中存放的是@EnableFeignClients与@FeignClient两个注解中的configuration属性值。
- // 这个属性值只有两类:
- // 第一类只有一个,其 key 为字符串 default + 当前启动类的全限定性类名 ,例如:
- // default.com.abc.ConsumerFeign8080, value 为@EnableFeignClients 的 defaultConfiguration属性值
- // 第二类有多个,其 key 为当前@FeignClient 的名称, value 为这个注解的 configuration 属性值
- private Map<String, C> configurations = new ConcurrentHashMap<>();
-
- private ApplicationContext parent;
-
- private Class<?> defaultConfigType;
-
- public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName,
- String propertyName) {
- this.defaultConfigType = defaultConfigType;
- this.propertySourceName = propertySourceName;
- this.propertyName = propertyName;
- }