国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring-cloud Feign 的深入理解

Spring-cloud Feign 的深入理解

2021-07-15 11:04Degaulle Java教程

這篇文章主要介紹了Spring-cloud Feign 的深入理解,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

feign的調用流程

讀取注解信息:enablefeignclients-->feignclientsregistrar-->feignclientfactorybean
feigh流程:reflectivefeign-->contract-->synchronousmethodhandler
相關configuration:feignclientsconfiguration,feignautoconfiguration,defaultfeignloadbalancedconfiguration,feignribbonclientautoconfiguration(ribbon)

在feignclientsregistrar中:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@override
public void registerbeandefinitions(annotationmetadata metadata,
    beandefinitionregistry registry) {
  //注冊feign配置信息
  registerdefaultconfiguration(metadata, registry);
  //注冊feign client
  registerfeignclients(metadata, registry);
}
 
private void registerfeignclient(beandefinitionregistry registry,
    annotationmetadata annotationmetadata, map<string, object> attributes) {
  string classname = annotationmetadata.getclassname();
  //準備注入feignclientfactorybean
  beandefinitionbuilder definition = beandefinitionbuilder
      .genericbeandefinition(feignclientfactorybean.class);
  ...
}

查看feignclientfactorybean:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@override
public object getobject() throws exception {
  feigncontext context = applicationcontext.getbean(feigncontext.class);
  //構建feign.builder
  feign.builder builder = feign(context);
  //如果注解沒有指定url
  if (!stringutils.hastext(this.url)) {
    string url;
    if (!this.name.startswith("http")) {
      url = "http://" + this.name;
    }
    else {
      url = this.name;
    }
    url += cleanpath();
    return loadbalance(builder, context, new hardcodedtarget<>(this.type,
        this.name, url));
  }
  //如果指定了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) {
      // 因為指定了url且classpath下有ribbon,獲取client的delegate(unwrap)
      // 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 targeter.target(this, builder, context, new hardcodedtarget<>(
      this.type, this.name, url));
}
 
protected <t> t loadbalance(feign.builder builder, feigncontext context,
    hardcodedtarget<t> target) {
  //獲取feign client實例
  client client = getoptional(context, client.class);
  if (client != null) {
    builder.client(client);
    //defaulttargeter或者hystrixtargeter
    targeter targeter = get(context, targeter.class);
    //調用builder的target,其中就調用了feign的newinstance
    return targeter.target(this, builder, context, target);
  }
 
  throw new illegalstateexception(
      "no feign client for loadbalancing defined. did you forget to include spring-cloud-starter-netflix-ribbon?");
}

在feignclientsconfiguration配置了feign.builder,prototype類型:

?
1
2
3
4
5
6
@bean
@scope("prototype")
@conditionalonmissingbean
public feign.builder feignbuilder(retryer retryer) {
  return feign.builder().retryer(retryer);
}

feign的builder.build返回了一個reflectivefeign:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public feign build() {
 synchronousmethodhandler.factory synchronousmethodhandlerfactory =
   new synchronousmethodhandler.factory(client, retryer, requestinterceptors, logger,
                      loglevel, decode404);
 parsehandlersbyname handlersbyname =
   new parsehandlersbyname(contract, options, encoder, decoder,
               errordecoder, synchronousmethodhandlerfactory);
 //reflectivefeign構造參數
 //parsehandlersbyname作用是通過傳入的target返回代理接口下的方法的各種信息(methodhandler)
 //contract:解析接口的方法注解規則,生成methodmetadata
 //options:request超時配置
 //encoder:請求編碼器
 //decoder:返回解碼器
 //errordecoder:錯誤解碼器
 //synchronousmethodhandler.factory是構建synchronousmethodhandler的工廠
 //client:代表真正執行http的組件
 //retryer:該組決定了在http請求失敗時是否需要重試
 //requestinterceptor:請求前的攔截器
 //logger:記錄日志組件,包含各個階段記錄日志的方法和留給用戶自己實現的log方法
 //logger.level:日志級別
 //decode404:處理404的策略,返回空還是報錯
 //synchronousmethodhandlerfactory通過所有的信息去包裝一個synchronousmethodhandler,在調用invoke方法的時候執行http
 return new reflectivefeign(handlersbyname, invocationhandlerfactory);
}

在調用feign.builder的target的時候,調用了reflectivefeign.newinstance:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 * creates an api binding to the {@code target}. as this invokes reflection, care should be taken
 * to cache the result.
 */
@suppresswarnings("unchecked")
@override
//接收target參數(包含feign代理接口的類型class,名稱,http url)
public <t> t newinstance(target<t> target) {
 //首先通過**parsehandlersbyname**解析出接口中包含的方法,包裝requesttemplate,組裝成<name, methodhandler>
 map<string, methodhandler> nametohandler = targettohandlersbyname.apply(target);
 map<method, methodhandler> methodtohandler = new linkedhashmap<method, methodhandler>();
 //接口default方法list
 list<defaultmethodhandler> defaultmethodhandlers = new linkedlist<defaultmethodhandler>();
 
 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)));
  }
 }
 //invocationhandlerfactory.default()返回了一個reflectivefeign.feigninvocationhandler對象,通過傳入的methodhandler map 調用目標對象的對應方法
 invocationhandler handler = factory.create(target, methodtohandler);
 //生成jdk代理對象
 t proxy = (t) proxy.newproxyinstance(target.type().getclassloader(), new class<?>[]{target.type()}, handler);
 //綁定接口的默認方法到代理對象
 for(defaultmethodhandler defaultmethodhandler : defaultmethodhandlers) {
  defaultmethodhandler.bindto(proxy);
 }
 return proxy;
}

生成feign代理對象的基本流程圖:

Spring-cloud Feign 的深入理解

當調用接口方法時,實際上就是調用代理對象invoke方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@override
public object invoke(object[] argv) throws throwable {
 //工廠創建請求模版
 requesttemplate template = buildtemplatefromargs.create(argv);
 //每次克隆一個新的retryer
 retryer retryer = this.retryer.clone();
 while (true) {
  try {
   //這里調用實際的feign client execute
   return executeanddecode(template);
  } catch (retryableexception e) {
   //失敗重試
   retryer.continueorpropagate(e);
   if (loglevel != logger.level.none) {
    logger.logretry(metadata.configkey(), loglevel);
   }
   continue;
  }
 }
}

在defaultfeignloadbalancedconfiguration里實例化了loadbalancerfeignclient

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@override
public response execute(request request, request.options options) throws ioexception {
  try {
    uri asuri = uri.create(request.url());
    string clientname = asuri.gethost();
    uri uriwithouthost = cleanurl(request.url(), clientname);
    //delegate這里是client.default實例,底層調用的是java.net原生網絡訪問
    feignloadbalancer.ribbonrequest ribbonrequest = new feignloadbalancer.ribbonrequest(
        this.delegate, request, uriwithouthost);
 
    iclientconfig requestconfig = getclientconfig(options, clientname);
    //executewithloadbalancer會根據ribbon的負載均衡算法構建url,這里不展開
    return lbclient(clientname).executewithloadbalancer(ribbonrequest,
        requestconfig).toresponse();
  }
  catch (clientexception e) {
    ioexception io = findioexception(e);
    if (io != null) {
      throw io;
    }
    throw new runtimeexception(e);
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://segmentfault.com/a/1190000018077675

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美日韩精品在线 | 精品一区二区三区免费视频 | 国产欧美日韩在线观看 | 国产一区a | 久久a视频 | 亚洲黄色在线 | 狠狠色噜噜狠狠狠8888米奇 | 亚洲免费不卡视频 | 国产亚洲精品美女久久久久久久久久 | 国产成人黄色av | 久久久国产精品视频 | 国产欧美精品一区二区三区 | 日本福利一区二区 | 国产精品99久久久久久久vr | 国产视频一二三区 | 亚洲不卡高清视频 | 在线一级黄色片 | 91精品国产综合久久久久久 | 午夜精品久久久久久 | 久久精品小视频 | 欧美午夜三级视频 | 男女xx网站 | 一区二区三区在线视频播放 | 亚洲福利精品 | 欧美亚洲自拍偷拍 | 久久午夜网站 | 狠狠躁夜夜躁人人爽天天天天97 | 色网站视频 | 色婷婷一区二区 | 国产精品欧美久久久久一区二区 | 欧美一区二区三区在线视频 | 日韩中文字幕在线视频 | 久久高清精品 | 日韩精品视频免费在线观看 | 国产一区av在线 | 亚洲精品国产第一综合99久久 | 日韩免费网站 | 黄网站在线观看 | 日韩一区二区三区视频 | 成人免费视频在线观看 | 曰韩一级鸥美一级 |