Spring Cloud OpenFeign 源码解析(一)重要类与接口解析

重要类与接口解析

1. @EnableFeignClients

在这里插入图片描述
该注解中一共有5个属性:
在这里插入图片描述
我们依次看,这些属性流程分析的时候都会用到:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {

	/**
	 * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
	 * {@link #basePackages()}属性的别名。允许更简洁的注释
	 * 
	 * declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
	 * {@code @ComponentScan(basePackages="org.my.pkg")}.
	 * @return the array of 'basePackages'.
	 */
	String[] value() default {};

	/**
	 * Base packages to scan for annotated components.
	 * 扫描带注解组件的基本包路径
	 * <p>
	 * {@link #value()} is an alias for (and mutually exclusive with) this attribute.
	 * value()是此属性的别名(并与其互斥)。
	 * <p>
	 * Use {@link #basePackageClasses()} for a type-safe alternative to String-based
	 * package names.
	 * 使用{@link #basePackageClasses()}作为基于字符串的包名的类型安全替代方案。
	 * 
	 * @return the array of 'basePackages'.
	 */
	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.
	 * 类型安全的{@link #basePackages()}的替代方案,用于指定要扫描的包以寻找带注解的组件。
	 * 每个指定类的包将被扫描。
	 * <p>
	 * 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'.
	 * 考虑在每个包中创建一个特殊的无操作标记类或接口,
	 * 该标记类或接口除了被该属性引用之外没有其他用途。
	 * 
	 * 可以用类或接口的方式代替字符串方式指定包名。
	 */
	Class<?>[] basePackageClasses() default {};

	/**
	 * A custom <code>@Configuration</code> for all feign clients. Can contain override
	 * <code>@Bean</code> definition for the pieces that make up the client, for instance
	 * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
	 * 一个自定义的@Configuration用于所有 feign 客户端。可以包含组成客户端的各个组件的重
	 * 写@Bean定义,例如{@link feign.codec。解码器},{@link feign.codec。编码器},
	 * {@link feign.Contract}。
	 * 
	 * feign clients的全局配置,配置的是构成feign client的组件的具体实现类,这些类的实例最终
	 * 会放到每个feign client专门的一个子容器中
	 * 
	 * @see FeignClientsConfiguration for the defaults
	 * @return list of default configurations
	 */
	Class<?>[] defaultConfiguration() default {};

	/**
	 * List of classes annotated with @FeignClient. If not empty, disables classpath
	 * scanning.
	 * 用@FeignClient注解的类列表。如果不为空,则禁用类路径扫描。
	 * 
	 * 通过该属性直接指定要加载哪些@FeignClient接口
	 * 用这个属性,就不会进行包路径扫描了
	 * @return list of FeignClient classes
	 */
	Class<?>[] clients() default {};

}

defaultConfiguration属性可以为所有feign客户端配置默认的全局配置,可以配置如下组件:

  • Decoder
    在这里插入图片描述

  • Encoder
    在这里插入图片描述

  • Contract
    在这里插入图片描述
    就是这个接口,允许OpenFeign 支持处理 SpringMVC 相关的注解:
    在这里插入图片描述
    有兴趣自己看吧。

2. @FeignClient

快速入门第三章 OpenFeign 曾用的Demo:
在这里插入图片描述
看到该注解中属性还是比较多的:
在这里插入图片描述

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {

	/**
	 * 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}.
	 * 带有可选协议前缀的服务名称。{@link #name() name}的同义词。无论是否提供url,
	 * 都必须为所有客户端指定名称。可以指定为属性键,例如:${propertyKey}。
	 * 
	 * 例如http://xxxxx:port/aaa/bb/cc   xxxxx就是服务名称
	 * 
	 * 属性键$ {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
	 * 带有可选协议前缀的服务id。{@link #value() value}的同义词。
	 * 过时了,使用{@link #name() name}代替
	 * 
	 * @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.
	 * 如果存在,它将被用作bean名,代替name属性,但不会用作服务id。
	 * 
	 * @return bean name instead of name if present
	 */
	String contextId() default "";
	
	/**
	 * @return The service id with optional protocol prefix. Synonym for {@link #value()
	 * value}.
	 * 带有可选协议前缀的服务id。{@link #value() value}的同义词。
	 */
	@AliasFor("value")
	String name() default "";

	//--------- 分割线上面这些属性作用都是一样的,代表微服务名称、服务ID -----------

	/**
	 * @return the <code>@Qualifier</code> value for the feign client.
	 * feign client的@Qualifier值。
	 * 根据Class Type注入,如果存在多个会报错,就需要根据名称注入@Qualifier可以指定名称
	 */
	String qualifier() default "";

	/**
	 * @return an absolute URL or resolvable hostname (the protocol is optional).
	 * 绝对URL或可解析主机名(协议是可选的)。
	 * 
	 * 配置这个相当于直连方式,例如url="localhost:8080"
	 * 这样就不会根据微服务名称负载均衡了
	 */
	String url() default "";

	/**
	 * @return whether 404s should be decoded instead of throwing FeignExceptions
	 * 如果发生FeignExceptions是否需要返回404
	 */
	boolean decode404() default false;

	/**
	 * A custom <code>@Configuration</code> for the feign client. Can contain override
	 * <code>@Bean</code> definition for the pieces that make up the client, for instance
	 * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
	 * 一个自定义的@Configuration用于feign client。可以包含组成客户端的组件的重写@Bean定义,
	 * 例如{@link feign.codec。解码器},{@link feign.codec。编码器},{@link feign.Contract}。
	 * 
	 * 这个配置相当于是局部配置,某一个feign client专门的配置
	 * 
	 * @see FeignClientsConfiguration for the defaults
	 * @return list of configurations for feign client
	 */
	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.
	 * 指定Feign client接口的服务降级类。服务降级类必须实现由该注解注释的接口,
	 * 并且必须是一个有效的spring bean。
	 * 
	 * @return fallback class for the specified Feign client interface
	 */
	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.
	 * 为指定的Feign client接口定义一个服务降级工厂。服务降级工厂必须生成服务降级类的实例,
	 * 这些实例实现了由{@link FeignClient}注释的接口。服务降级工厂必须是一个有效的spring bean。
	 * 
	 * @see feign.hystrix.FallbackFactory for details.
	 * @return fallback factory for the specified Feign client interface
	 */
	Class<?> fallbackFactory() default void.class;

	/**
	 * @return path prefix to be used by all method-level mappings. Can be used with or
	 * without <code>@RibbonClient</code>.
	 * 所有方法级映射使用的路径前缀。可与或不与@RibbonClient一起使用。
	 */
	String path() default "";

	/**
	 * @return whether to mark the feign proxy as a primary bean. Defaults to true.
	 * 是否将feign代理标记为主bean。默认值为true。
	 * 
	 * 和@Primary注解类似,同一个接口多个实现类中
	 * 根据类型注入时候会首选被@Primary标记的实现类
	 * 
	 * 每个feign client接口都会为其生成一个代理类,这里是为这个代理类标记为Primary
	 */
	boolean primary() default true;

}

3. FeignClientSpecification 类

FeignClientSpecification 是一个 Feign Client 的生成规范,可以简单理解为是@EnableFeignClients注解和@FeignClient注解解析后数据存放的一个类,通过bean扫描,将扫描到的@EnableFeignClients注解的defaultConfiguration属性、@FeignClient注解的configuration属性维护在这个类中,将来初始化FeignClient子容器时会将这些类实例化到子容器,这些配置类实例都是Feign Cient构建所依赖的组件:

class FeignClientSpecification implements NamedContextFactory.Specification {
	//feignClient的名称,就是服务名、服务id
	private String name;
	//当前feignClient的配置类
	private Class<?>[] configuration;

	FeignClientSpecification() {
	}

	FeignClientSpecification(String name, Class<?>[] configuration) {
		this.name = name;
		this.configuration = configuration;
	}
	...
}

4. FeignContext 类

FeignContext 是 OpenFeign 的上下文对象,也是 Feign Client 的工厂类。
在这里插入图片描述
解释:就是一个Feign Client的工厂,生成Feign Client实例的。它会为每一个要创建的feign客户端(即feign client 接口)都创建一个子容器,并在子容器中注册FeignClient规范类中的配置类,这些类实例都是Feign Client创建所依赖的一些组件。而子容器的父容器就是整个应用的Spring容器。

重点要看一下父类:
在这里插入图片描述

configurations 维护的就是不同Feign Client名称对应的FeignClient规范。
其中包含了一个特殊的,全局的FeignClient规范:

  • 全局的FeignClient规范:key 为 default + 当前启动类的全限定性类名,value 就是FeignClientSpecification,其configuration属性是@EnableFeignClients 中的 defaultConfiguration 属性值。这个 Entry 只有一个。就是全局的FeignClient规范
  • 局部的FeignClient规范: key 为服务id,服务名称,value 就是FeignClientSpecification,其configuration属性是@FeignClient 的 configuration 属性值。当前应用中有多少个这个 Feign Client,那么这里就会包含多少个这种 Entry。就是每个FeignClient专门的FeignClient规范

5. BeanDefinition 接口

BeanDefinition 是一个 Bean 定义器,这个是Spring框架中的,OpenFeign 和 Spring 整合了嘛,初始化阶段扫描到的所有组件等都是作为BeanDefinition在Spring容器中的。
在这里插入图片描述
Spring解析xml时就会把一个<bean/>标签解析成一个BeanDefinition实例,最终通过BeanDefintion在Spring容器中生成一个Bean。

6. BeanDefinitionRegistry 接口

BeanDefinitionRegistry 是一个 BeanDefinition 注册表。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

犬豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值