Open Feign整个核心的调用过程大致如下:
下面根据源码详细分析:
// 通过开启feign注解引入FeignClientsRegistrar类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
//.....
}
FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar类,重写registerBeanDefinitions方法可以自定义bean在spring中的注册:
//自定义注册bean到spring容器
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
//...
//自定义实现注册bean
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
this.registerDefaultConfiguration(metadata, registry);
this.registerFeignClients(metadata, registry);
}
//扫描包所有加了@FeignClient的接口类,并将其注册到spring容器中。
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//...
Iterator var17 = ((Set)basePackages).iterator();
while(var17.hasNext()) {
String basePackage = (String)var17.next();
Set candidateComponents = scanner.findCandidateComponents(basePackage);
Iterator var21 = candidateComponents.iterator();
while(var21.hasNext()) {
BeanDefinition candidateComponent = (BeanDefinition)var21.next();
if (candidateComponent instanceof AnnotatedBeanDefinition) {
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 = this.getClientName(attributes);
this.registerClientConfiguration(registry, name, attributes.get("configuration"));
this.registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}
}
2.接着上面的registerFeignClient()方法,成feign client bean的包装类FeignClientFactoryBean,并将@FeignClient注解的属性注册到bean中。注册的FeignClientFactoryBean,是一个包装了我们需要执行的rpc服务的请求的类、url、服务名称以及回调方法等。
//生成feign client bean的包装类FeignClientFactoryBean,并将@FeignClient注解的属性注册到bean中。
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map attributes) {
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
this.validate(attributes);
definition.addPropertyValue("url", this.getUrl(attributes));
definition.addPropertyValue("path", this.getPath(attributes));
String name = this.getName(attributes);
definition.addPropertyValue("name", name);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(2);
String alias = name + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
boolean primary = (Boolean)attributes.get("primary");
beanDefinition.setPrimary(primary);
String qualifier = this.getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
FeignClientFactoryBean类定义:
private Class> type;
private String name;
private String url;
private String path;
private boolean decode404;
private ApplicationContext applicationContext;
private Class> fallback;
private Class> fallbackFactory;
3.FeignClientFactoryBean实现了FactoryBean
public interface FactoryBean {
@Nullable
T getObject() throws Exception;
@Nullable
Class> getObjectType();
default boolean isSingleton() {
return true;
}
//获取代理对象
public Object getObject() throws Exception {
FeignContext context = (FeignContext)this.applicationContext.getBean(FeignContext.class);
Builder builder = this.feign(context);
String url;
//FeignClient不存在url的走负载均衡器
if (!StringUtils.hasText(this.url)) {
if (!this.name.startsWith("http")) {
url = "http://" + this.name;
} else {
url = this.name;
}
url = url + this.cleanPath();
return this.loadBalance(builder, context, new HardCodedTarget(this.type, this.name, url));
//负载均衡
protected T loadBalance(Builder builder, FeignContext context, HardCodedTarget target) {
Client client = (Client)this.getOptional(context, Client.class);
if (client != null) {
builder.client(client);
Targeter targeter = (Targeter)this.get(context, Targeter.class);
return targeter.target(this, builder, context, target);
//获取目标对象
public T target(FeignClientFactoryBean factory, Builder feign, FeignContext context, HardCodedTarget target) {
return feign.target(target);
}
public T target(Target target) {
return this.build().newInstance(target);
}
4.生成默认的处理方法FeignInvocationHandler实现了jdk自带的动态代理调用接口InvocationHandler,并且为目标类生成代理类;
public T newInstance(Target target) {
//InvocationHandler最终执行的方法
Map nameToHandler = this.targetToHandlersByName.apply(target);
//...
//创建FeignInvocationHandler包装类,该类实现了jdk动态代理默认需要实现的接口InvocationHandler,后续通过invoke()方法转发到nameToHandler中处理
InvocationHandler handler = this.factory.create(target, methodToHandler);
//创建动态代理对象
T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
Iterator var12 = defaultMethodHandlers.iterator();
}
//创建FeignInvocationHandler包装类Target(class、name、url),dispatchd请求分发
public InvocationHandler create(Target target, Map dispatch) {
return new FeignInvocationHandler(target, dispatch);
}
public InvocationHandler create(Target target, Map dispatch) {
return new FeignInvocationHandler(target, dispatch);
}
//获取SynchronousMethodHandler类
public Map apply(Target key) {
for(Iterator var4 = metadata.iterator(); var4.hasNext(); result.put(md.configKey(), this.factory.create(key, md, (Factory)buildTemplate, this.options, this.decoder, this.errorDecoder))) {
}
//handler重写后的invoke()方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!"equals".equals(method.getName())) {
if ("hashCode".equals(method.getName())) {
return this.hashCode();
} else {
return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);
}
public MethodHandler create(Target> target, MethodMetadata md, feign.RequestTemplate.Factory buildTemplateFromArgs, Options options, Decoder decoder, ErrorDecoder errorDecoder) {
return new SynchronousMethodHandler(target, this.client, this.retryer, this.requestInterceptors, this.logger, this.logLevel, md, buildTemplateFromArgs, options, decoder, errorDecoder, this.decode404);
}
//Target的属性
public interface Target {
Class type();
String name();
String url();
}
5.然后走SynchronousMethodHandler的invoke()方法进行真正的rpc调用返回结果。
//SynchronousMethodHandler调用invoke()方法,开始执行请求
public Object invoke(Object[] argv) throws Throwable {
RequestTemplate template = this.buildTemplateFromArgs.create(argv);
Retryer retryer = this.retryer.clone();
while(true) {
try {
return this.executeAndDecode(template);
} catch (RetryableException var5) {
retryer.continueOrPropagate(var5);
if (this.logLevel != Level.NONE) {
this.logger.logRetry(this.metadata.configKey(), this.logLevel);
}
}
}
}
然后走到client真正开始执行请求的地方:
6.默认的client是LoadBalancerFeignClient,采用负载均衡策略的方式执行我们请求:
下一篇将进一步分析LoadBalancer负载均衡器,讲述lb-ribbon涉及的组件和底层工作原理。