背景

上一篇介绍了Feign源码初始化的一部分,内容主要是,@EnableFeignClients、@FeignClient这些注解,都支持设置一些自定义的配置类:

A custom @Configuration for all feign clients. Can contain override @Bean definition
for the pieces that make up the client, for instance feign.codec.Decoder,
feign.codec.Encoder, feign.Contract.

每个被@EnableFeignClients、@FeignClient注解的类都会对应生成一个bean,类型为:org.springframework.cloud.openfeign.FeignClientSpecification:

public class FeignClientSpecification implements NamedContextFactory.Specification {

	private String name;

	private Class<?>[] configuration;

即使没定义自定义的配置类,这个bean照样生成,只是里面的configuration字段是null。

这些bean都不是spring boot那种自动装配类,因为自动装配类一般来说,都是带条件的,比如要检测到classpath中有某个类,某个property的值等于xxx。

今天,就简单介绍下,Feign启动过程中,自动装配的那些类。

项目简介

自动装配有很多条件都是基于类是否存在来判断,咱们先看看classpath中有啥,主要就是web、nacos服务发现、feign、loadbalancer。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

当然,这里是要通过nacos进行服务发现的:

spring.cloud.nacos.discovery.username=111
spring.cloud.nacos.discovery.password=222
spring.cloud.nacos.discovery.server-addr=1.1.1.1:8848
spring.cloud.nacos.discovery.namespace=test

Feign调用的client代码:

package com.example.demo.demos.nacosdiscoveryconsumer;

import org.springframework.cloud.openfeign.FeignClient;

@FeignClient("echo-service-provider")
public interface EchoService { @GetMapping("/echo/{message}")
String echo(@PathVariable("message") String message);
}

手动梳理装配类

稍微了解spring boot的自动装配的话,大概知道,在starter那些依赖中,jar文件一般没有实质内容,没有class啥的,主要的内容还是pom文件,里面定义了该starter依赖的那些jar:

pom依赖主要包含feign自身、spring对feign的集成、spring-loadbalancer:

<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>11.10</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<version>3.1.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.1.6</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>

我们看看spring-cloud-openfeign-core这个依赖,这个spring-cloud-openfeign-core-3.1.7.pom呢,里面定义了很多底层依赖,而spring-cloud-openfeign-core-3.1.7.jar,则不再是无实质内容了:

大家看到我上图框的spring.factories文件,大概就知道,这个东西是和自动装配有关系的。

我们打开看看:

里面主要就是定义了,需要自动装配的配置类。

比如第一个类:org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration

这些类得特征是:都是有条件的,这也符合自动装配的逻辑,自动装配就是猜测你需要某些类,猜测那是需要依据的,依据就是:检查你的各种上下文,就跟现在那些短视频推荐一样的,猜你喜欢嘛。

这边简单汇总下,就是这5个自动装配类:

org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration,\
org.springframework.cloud.openfeign.FeignAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignContentGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration

接下来,看看spring-loadbalancer那个依赖,盘一盘它:

spring-cloud-starter-loadbalancer-3.1.6.jar,和其他starter一样,里面啥都没有;

spring-cloud-starter-loadbalancer-3.1.6.pom,主要依赖如下:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>3.1.6</version>
<scope>compile</scope>
</dependency>

该依赖如下:

主要包含如下几个自动装配类:

org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration,\
org.springframework.cloud.loadbalancer.security.OAuth2LoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerStatsAutoConfiguration

至于nacos,也是一样的套路盘起来,但是,它要直接一点,直接starter里面就是实质内容了:

引入的自动配置类有:

  com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\
com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration,\
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration,\
com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration

但以上就完了吗,不是。spring-cloud-loadbalancer是属于spring-cloud-commons的,在commons的jar包中,也有相关的自动配置类:

org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\

这边汇总下吧:

org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration,\
org.springframework.cloud.openfeign.FeignAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignContentGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration,\
org.springframework.cloud.loadbalancer.security.OAuth2LoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerStatsAutoConfiguration com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\
com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration,\
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration,\
com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\

这一下,就是几十个自动装配类,真他么多。

注意,这里面还有两个名字相同,包名不同的:

自动配置类最终引入了哪些bean

自动装配类都是相当复杂的,基于各种条件的计算,很多都不是一眼就能看出来的,有些和顺序还息息相关,比如,ConditionalOnMissingBean,这个就很有意思,在没有bean存在的情况下才自动装配,但我之前遇到过,有两个自动装配类,都加了这个注解,那,最终到底是哪个自动装配进去呢?

所以,如果项目复杂,可以考虑打开如下日志开关:

logging.level.org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener=DEBUG

就会打印如下的日志,哪些装配了,哪些没装配,一目了然:

spring boot actuator的actuator/conditions也支持动态查看这个信息,甚至可以看到各个spring容器的:

如果想知道某个自动装配类中,哪些bean匹配了,哪些bean没匹配上,只能ctrl + f了,比如Feign这个装配类:

org.springframework.cloud.openfeign.FeignAutoConfiguration

相当于匹配上了如下两个bean:

这边累计汇总下,装配成功的:

  • org.springframework.cloud.openfeign.FeignAutoConfiguration及内部的:

    FeignAutoConfiguration、

    FeignAutoConfiguration.DefaultFeignTargeterConfiguration

    FeignAutoConfiguration.DefaultFeignTargeterConfiguration#feignTargeter

  • org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration,内部类/method:无,这个类是靠import引入其他configuration的

  • org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration

    LoadBalancerAutoConfiguration#zoneConfig

  • org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration

    org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration#loadBalancerRequestFactory

    org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration#loadBalancerRequestFactory

    org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig

    org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig#restTemplateCustomizer

  • BlockingLoadBalancerClientAutoConfiguration

    BlockingLoadBalancerClientAutoConfiguration#blockingLoadBalancerClient

    BlockingLoadBalancerClientAutoConfiguration#loadBalancerServiceInstanceCookieTransformer

    BlockingLoadBalancerClientAutoConfiguration#xForwarderHeadersTransformer

  • LoadBalancerCacheAutoConfiguration

    内部略,太多了,写了也记不住

  • NacosDiscoveryAutoConfiguration

    NacosDiscoveryAutoConfiguration#nacosProperties

    NacosDiscoveryAutoConfiguration#nacosServiceDiscovery

  • NacosServiceRegistryAutoConfiguration

    NacosServiceRegistryAutoConfiguration#nacosAutoServiceRegistration

    NacosServiceRegistryAutoConfiguration#nacosRegistration

  • NacosDiscoveryClientConfiguration

  • NacosServiceAutoConfiguration

  • UtilIPv6AutoConfiguration

  • AsyncLoadBalancerAutoConfiguration

  • LoadBalancerDefaultMappingsProviderAutoConfiguration

以上都是匹配上的,没匹配的都没写。这边写了一抹多,供查阅吧,重点的有一个要先摘出来说,它是属于没匹配上的:

LoadBalancerNacosAutoConfiguration:
Did not match:
- @ConditionalOnProperty (spring.cloud.loadbalancer.nacos.enabled=true) did not find property 'spring.cloud.loadbalancer.nacos.enabled' (OnPropertyCondition)

这是一个nacos包里的关于loadbalancer的自动配置类,当初就是因为这个类,让我遇到了些问题,才好好研究了下feign,写了这几篇,可以说的上是为了这盘醋包了这顿饺子,后面的文章会再说说这个类。

Feign源码解析:初始化过程(二)的更多相关文章

  1. Feign源码解析

    1. Feign源码解析 1.1. 启动过程 1.1.1. 流程图 1.1.2. 解释说明 Feign解析过程依赖Spring的初始化,它通过实现ImportBeanDefinitionRegistr ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  3. Feign源码解析系列-注册套路

    感谢不知名朋友的打赏,感谢你的支持! 开始 在追寻Feign源码的过程中发现了一些套路,既然是套路,就可以举一反三,所以值得关注. 这篇会详细解析Feign Client配置和初始化的方式,这些方式大 ...

  4. [spring源码] 小白级别的源码解析ioc(二)

    之前一篇,整体描述了一下 Spring的整体概况和 jar包的介绍. 现在开始进入具体的源码解析,从本篇开始,先介绍spring的ioc容器.之前也看过一些介绍spring源码的, 有的是只讲整体的接 ...

  5. JDK8源码解析 -- HashMap(二)

    在上一篇JDK8源码解析 -- HashMap(一)的博客中关于HashMap的重要知识点已经讲了差不多了,还有一些内容我会在今天这篇博客中说说,同时我也会把一些我不懂的问题抛出来,希望看到我这篇博客 ...

  6. junit源码解析--初始化阶段

    OK,我们接着上篇整理.上篇博客中已经列出的junit的几个核心的类,这里我们开始整理junit完整的生命周期. JUnit 的完整生命周期分为 3 个阶段:初始化阶段.运行阶段和结果捕捉阶段. 这篇 ...

  7. springmvc源码解析-初始化

    1.      概述 对于Web开发者,MVC模型是大家再熟悉不过的了,SpringMVC中,满足条件的请求进入到负责请求分发的DispatcherServlet,DispatcherServlet根 ...

  8. 分布式事务_02_2PC框架raincat源码解析-启动过程

    一.前言 上一节已经将raincat demo工程运行起来了,这一节来分析下raincat启动过程的源码 主要包括: 事务协调者启动过程 事务参与者启动过程 二.协调者启动过程 主要就是在启动类中通过 ...

  9. mybatis源码阅读-初始化过程(七)

    说明 mybatis初始化过程 就是解析xml到封装成Configuration对象 供后续使用 SqlSessionFactoryBuilder 代码例子 SqlSessionFactoryBuil ...

  10. Feign源码解析系列-那些注解们

    开始 Feign在Spring Cloud体系中被整合进来作为web service客户端,使用HTTP请求远程服务时能就像调用本地方法,可见在未来一段时间内,大多数Spring Cloud架构的微服 ...

随机推荐

  1. CodeForces 1343E Weights Distributing

    题意 多组样例 给定\(n,m,a,b,c\),给定一个长度为\(m\)的数组\(p[]\),给定\(m\)条边,构成一个\(n\)个点\(m\)条边的无向图,\(Mike\)想要从\(a\)走到\( ...

  2. Iphone通过ssh进行访问

    Iphone通过usb进行ssh访问文件系统 在公司里wifi很不给力,而我又想通过ssh访问我的iphone,进行一些权限访问,这时我们该 itunnel_mux_rev71这个工具可以帮我们的忙 ...

  3. ssm框架的事物控制

    事物控制统一在逻辑层的实现类中以注解的形式添加,例如:对UserServiceImpl中的addUser方法需要进行事物控制,操作如下: 1.此方法必须为public2.在方法名上边加入@Transa ...

  4. 我的 Windows 文件管理哲学

    前言   作为一个不合格的 Geek,我经常面临把 Windows 弄崩溃的尴尬处境,我的系统因此重装了一遍又一遍--不过在一次次的重装中,我逐渐总结出了于我个人而言行之有效的文件管理哲学,在此略做总 ...

  5. Solution -「洛谷 P4688」「YunoOI 2016」掉进兔子洞

    Description (Link)[https://www.luogu.com.cn/problem/P4688]. 每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的 ...

  6. Springboot实现注解判断权限

    Springboot实现注解判断权限 今天记录一下使用springboot的注解来给方法加权限 避免了每个方法都需要大量的权限判断 超级好用√ @ 目录 Springboot实现注解判断权限 1.创建 ...

  7. Go语言常用标准库——context

    文章目录 为什么需要Context 基本示例 全局变量方式 通道方式 官方版的方案 Context初识 Context接口 Background()和TODO() With系列函数 WithCance ...

  8. MySQL快速导入千万条数据(1)

    目录 一.命令行导入方式 二.LOAD DATA导入方式 对于传统的关系数据库如oracle,在大量数据导入方面的效率,我们一般有一个大概的认知,即1分钟以内可以导入千万条数据,而对于MySQL数据库 ...

  9. eclipse使用技巧和插件

    eclipse使用技巧和插件 本篇文章只列举了一部分技巧和插件,并没有包括大家都知道的快捷键和技巧,而是一些不经常用但又很方便的功能. 一,技巧 给Eclipse添加更方便的提示功能:Windows– ...

  10. Swagger系列:SpringBoot3.x中使用Knife4j

    目录 一.简介 二.版本说明 三.使用 四.效果图 一.简介 官网:https://doc.xiaominfo.com/ Knife4j是一个集Swagger2 和 OpenAPI3 为一体的增强解决 ...