springcloudopenfeign源碼實例解析

一、讀取注解信息

創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、歷城網(wǎng)絡(luò)推廣、重慶小程序開發(fā)、歷城網(wǎng)絡(luò)營銷、歷城企業(yè)策劃、歷城品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供歷城建站搭建服務(wù),24小時服務(wù)熱線:028-86922220,官方網(wǎng)址:bm7419.com

入口

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 {
。。。。
}

在注解中導(dǎo)入了 FeignClientsRegistrar類,用來像spring注冊,EnableFeignClients和FeignClient上面開發(fā)人員添加的注解信息

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

二、當(dāng)項目啟動,讀取@Autowired時會調(diào)用,實現(xiàn)了FactoryBean接口的FeignClientFactoryBean.getObject()方法

   @Override
   public Object getObject() throws Exception {
     return getTarget();
   }
<T> 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()有兩種返回結(jié)果的情況,其原理都一樣后來調(diào)用了 targeter.target()方法

package org.springframework.cloud.openfeign;

import feign.Feign;
import feign.Target;

/**
 * @author Spencer Gibb
 */
interface Targeter {

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

}

默認(rèn)實現(xiàn)類

package org.springframework.cloud.openfeign;

import feign.Feign;
import feign.Target;

/**
 * @author Spencer Gibb
 */
class DefaultTargeter implements Targeter {

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

}

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

public <T> T target(Target<T> 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()方法返回了創(chuàng)建代理類的對象,然后調(diào)用了創(chuàng)建代理的 newInstance方法

public <T> T newInstance(Target<T> target) {
  Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
  Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
  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)));
   }
  }
  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;
 }

最后,當(dāng)我們項目中使用 @Autowired注入時,就回調(diào)用工廠類 FeignClientFactoryBean方法的 getObject()方法 返回我們的代理對象

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

網(wǎng)站題目:springcloudopenfeign源碼實例解析
路徑分享:http://bm7419.com/article24/pcejje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT網(wǎng)站內(nèi)鏈、面包屑導(dǎo)航、移動網(wǎng)站建設(shè)品牌網(wǎng)站建設(shè)、企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)