重要類與接口解析
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 系統資料庫。