spring cloud openfeign源码分析

大体流程鱼骨图

 1.读取配置

 启动类上添加注解@EnableFeignClients,工程启动后会自动读取注解上的配置

1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.TYPE)
3 @Documented
4 @Import(FeignClientsRegistrar.class)
5 public @interface EnableFeignClients {
6 。。。。。。属性省略
7 }

这里我们可以看到 EnableFeignClients 注解引入了配置类 org.springframework.cloud.openfeign.FeignClientsRegistrar

registerBeanDefinitions方法提供了注册 EnableFeignClients注解信息和 FeignClient信息的功能
1 @Override
2     public void registerBeanDefinitions(AnnotationMetadata metadata,
3             BeanDefinitionRegistry registry) {
4         registerDefaultConfiguration(metadata, registry);
5         registerFeignClients(metadata, registry);
6     }

 拼接注解信息放在 definition中,然后交给spring容器管理

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients

 1 private void registerFeignClient(BeanDefinitionRegistry registry,
 2             AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
 3         String className = annotationMetadata.getClassName();
 4                 //根据工厂类获得对象
 5         BeanDefinitionBuilder definition = BeanDefinitionBuilder
 6                 .genericBeanDefinition(FeignClientFactoryBean.class);
 7         validate(attributes);
 8         definition.addPropertyValue("url", getUrl(attributes));
 9         definition.addPropertyValue("path", getPath(attributes));
10         String name = getName(attributes);
11         definition.addPropertyValue("name", name);
12         String contextId = getContextId(attributes);
13         definition.addPropertyValue("contextId", contextId);
14         definition.addPropertyValue("type", className);
15         definition.addPropertyValue("decode404", attributes.get("decode404"));
16         definition.addPropertyValue("fallback", attributes.get("fallback"));
17         definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
18         definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
19 
20         String alias = contextId + "FeignClient";
21         AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
22 
23         boolean primary = (Boolean) attributes.get("primary"); // has a default, won't be
24                                                                 // null
25 
26         beanDefinition.setPrimary(primary);
27 
28         String qualifier = getQualifier(attributes);
29         if (StringUtils.hasText(qualifier)) {
30             alias = qualifier;
31         }
32 
33         BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
34                 new String[] { alias });
35         BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
36     }        

 

2.创建代理实例方法

feign.ReflectiveFeign#newInstance

 1   public <T> T newInstance(Target<T> target) {
 2         Map<String, MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
 3         Map<Method, MethodHandler> methodToHandler = new LinkedHashMap();
 4         List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
 5         Method[] var5 = target.type().getMethods();
 6         int var6 = var5.length;
 7 
 8         for(int var7 = 0; var7 < var6; ++var7) {
 9             Method method = var5[var7];
10             if (method.getDeclaringClass() != Object.class) {
11                 if (Util.isDefault(method)) {
12                     DefaultMethodHandler handler = new DefaultMethodHandler(method);
13                     defaultMethodHandlers.add(handler);
14                     methodToHandler.put(method, handler);
15                 } else {
16                     methodToHandler.put(method, (MethodHandler)nameToHandler.get(Feign.configKey(target.type(), method)));
17                 }
18             }
19         }
20      //在这里我们可以看到feign创建了一个代理类
21         InvocationHandler handler = this.factory.create(target, methodToHandler);
22         T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
23         Iterator var12 = defaultMethodHandlers.iterator();
24 
25         while(var12.hasNext()) {
26             DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
27             defaultMethodHandler.bindTo(proxy);
28         }
29 
30         return proxy;
31     }

创建代理类的方法

1         public InvocationHandler create(Target target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch) {
2             return new FeignInvocationHandler(target, dispatch);
3         }
4     }

代理类的invoke方法,feign.ReflectiveFeign.FeignInvocationHandler#invoke

 1  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 2             if (!"equals".equals(method.getName())) {
 3                 if ("hashCode".equals(method.getName())) {
 4                     return this.hashCode();
 5                 } else {
 6                     return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);
 7                 }
 8             } else {
 9                 try {
10                     Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
11                     return this.equals(otherHandler);
12                 } catch (IllegalArgumentException var5) {
13                     return false;
14                 }
15             }
16         }

查看上面的invoke方法是怎么实现的

1     public interface MethodHandler {
2         Object invoke(Object[] var1) throws Throwable;
3     }

找到实现类 feign.SynchronousMethodHandler#invoke

 1  public Object invoke(Object[] argv) throws Throwable {
 2         //这里创建了一个template
 3         RequestTemplate template = this.buildTemplateFromArgs.create(argv);
 4         Options options = this.findOptions(argv);
 5         Retryer retryer = this.retryer.clone();
 6 
 7         while(true) {
 8             try {
 9     
10                 return this.executeAndDecode(template, options);
11             } catch (RetryableException var9) {
12                 RetryableException e = var9;
13 
14                 try {
15                     retryer.continueOrPropagate(e);
16                 } catch (RetryableException var8) {
17                     Throwable cause = var8.getCause();
18                     if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {
19                         throw cause;
20                     }
21 
22                     throw var8;
23                 }
24 
25                 if (this.logLevel != Level.NONE) {
26                     this.logger.logRetry(this.metadata.configKey(), this.logLevel);
27                 }
28             }
29         }
30     }        

 然后调用ribbon,执行rest请求 org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#execute

 1 @Override
 2     public Response execute(Request request, Request.Options options) throws IOException {
 3         try {
 4             URI asUri = URI.create(request.url());
 5             String clientName = asUri.getHost();
 6             URI uriWithoutHost = cleanUrl(request.url(), clientName);
 7             FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
 8                     this.delegate, request, uriWithoutHost);
 9 
10             IClientConfig requestConfig = getClientConfig(options, clientName);
11             return lbClient(clientName)
12                     .executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
13         }
14         catch (ClientException e) {
15             IOException io = findIOException(e);
16             if (io != null) {
17                 throw io;
18             }
19             throw new RuntimeException(e);
20         }
21     }

-----------------------------------------------------------------------------------------------------------------------------

大部分都是贴的源码,本文只是为了记录一次feign的大致实现思想,其中很多精妙的方式并没有提及

原文地址:https://www.cnblogs.com/yechen2019/p/11661226.html