栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring cloud openfeign 源码实例解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring cloud openfeign 源码实例解析

一、读取注解信息

入口

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;


@SpringBootApplication
@EnableFeignClients
public class CjsPriceServiceApplication {

  public static void main(String[] args) {
    SpringApplication.run(CjsPriceServiceApplication.class, args);
  }

}

spring boot 项目启动后会自动扫描application上面的注解,@EnableFeignClients的注解如下

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@documented
@import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
。。。。
}

在注解中导入了 FeignClientsRegistrar类,用来像spring注册,EnableFeignClients和FeignClient上面开发人员添加的注解信息

@Override
  public void registerBeanDefinitions(Annotationmetadata metadata,
      BeanDefinitionRegistry registry) {
    registerDefaultConfiguration(metadata, registry);
    registerFeignClients(metadata, registry);
  }

二、当项目启动,读取@Autowired时会调用,实现了FactoryBean接口的FeignClientFactoryBean.getObject()方法

   @Override
   public Object getObject() throws Exception {
     return getTarget();
   }
 T getTarget() {
    FeignContext context = this.applicationContext.getBean(FeignContext.class);
    Feign.Builder builder = feign(context);

    if (!StringUtils.hasText(this.url)) {
      if (!this.name.startsWith("http")) {
 this.url = "http://" + this.name;
      }
      else {
 this.url = this.name;
      }
      this.url += cleanPath();
      return (T) loadBalance(builder, context,
   new HardCodedTarget<>(this.type, this.name, this.url));
    }
    if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
      this.url = "http://" + this.url;
    }
    String url = this.url + cleanPath();
    Client client = getOptional(context, Client.class);
    if (client != null) {
      if (client instanceof LoadBalancerFeignClient) {
 // not load balancing because we have a url,
 // but ribbon is on the classpath, so unwrap
 client = ((LoadBalancerFeignClient) client).getDelegate();
      }
      builder.client(client);
    }
    Targeter targeter = get(context, Targeter.class);
    return (T) targeter.target(this, builder, context,
 new HardCodedTarget<>(this.type, this.name, url));
  }

可以看到 getTarget()有两种返回结果的情况,其原理都一样后来调用了 targeter.target()方法

package org.springframework.cloud.openfeign;

import feign.Feign;
import feign.Target;


interface Targeter {

   T target(FeignClientFactoryBean factory, Feign.Builder feign,
      FeignContext context, Target.HardCodedTarget target);

}

默认实现类

package org.springframework.cloud.openfeign;

import feign.Feign;
import feign.Target;


class DefaultTargeter implements Targeter {

  @Override
  public  T target(FeignClientFactoryBean factory, Feign.Builder feign,
      FeignContext context, Target.HardCodedTarget target) {
    return feign.target(target);
  }

}

然后再看 feign.target(target);方法

public  T target(Target target) {
   return build().newInstance(target);
  }

  public Feign build() {
   SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
     new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
logLevel, decode404, closeAfterDecode, propagationPolicy);
   ParseHandlersByName handlersByName =
     new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder,
errorDecoder, synchronousMethodHandlerFactory);
   return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
  }
 }

build()方法返回了创建代理类的对象,然后调用了创建代理的 newInstance方法

public  T newInstance(Target target) {
  Map nameToHandler = targetToHandlersByName.apply(target);
  Map methodToHandler = new linkedHashMap();
  List defaultMethodHandlers = new linkedList();

  for (Method method : target.type().getMethods()) {
   if (method.getDeclaringClass() == Object.class) {
    continue;
   } else if (Util.isDefault(method)) {
    DefaultMethodHandler handler = new DefaultMethodHandler(method);
    defaultMethodHandlers.add(handler);
    methodToHandler.put(method, handler);
   } else {
    methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
   }
  }
  InvocationHandler handler = factory.create(target, methodToHandler);
  T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
    new Class[] {target.type()}, handler);

  for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
   defaultMethodHandler.bindTo(proxy);
  }
  return proxy;
 }

最后,当我们项目中使用 @Autowired注入时,就回调用工厂类 FeignClientFactoryBean方法的 getObject()方法 返回我们的代理对象

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/136707.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号