Ribbon&Feign
2022-10-01 18:45:26 6 举报
SpringCloud 集成 Feign & Ribbon 源码、调用流程。
作者其他创作
大纲/内容
create()
updateListOfServers();
将接口bean替换为FactoryBeanspring 在getBean()阶段会调用FactoryBean的getObject()方法
获取feign 上下文FeignContext context = applicationContext.getBean(FeignContext.class);
会在spring的BeanDefinition注册阶段导入FeignClientsRegistrar bean定义@Import(FeignClientsRegistrar.class)
chooseServer
创建Feign上下文,在getObject创建动态代理阶段会从中获取FeignClient@Beanpublic FeignContext feignContext() { FeignContext context = new FeignContext(); context.setConfigurations(this.configurations); return context;}
executeAndDecode()
return svc;
spring启动时创建rule(ZoneAvoidanceRule)rule.choose(key)
定时更新本地服务列表缓存enableAndInitLearnNewServersFeature();
枚举
Feign自动配置类FeignAutoConfiguration
build().newInstance(target);
Server server = loadBalancerContext.getServerFromLoadBalancer()
获取FactoryBean的beanDefinitionBeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
向FactoryBean中设置@FeignClient注解上设置的属性值
invocationHandlerFactory
RibbonClientConfiguration配置中创建LoadBalancer到Spring容器
registerBeanDefinitions()自定义注册beanDefinition
updateListOfServers();
@Bean@ConditionalOnMissingBeanpublic ILoadBalancer()
HystrixTargeter.target()
Targeter动态代理创建入口@Bean@ConditionalOnMissingBeanpublic Targeter feignTargeter() { return new HystrixTargeter();}
目标方法动态代理,返回动态代理beangetTarget()
配置扫描器只扫描带有@FeignClient注解的接口scanner.addIncludeFilter(annotationTypeFilter);
注册下面类的BeanDefinitionFeignClientSpecification.class
servers = serverListImpl.getUpdatedListOfServers();
build()
serverListUpdater.start(updateAction);
getObject()
获取扫描包路径basePackages = getBasePackages(metadata);
newInstance(target)
1
@EnableFeignClients
创建feign客服端默认配置属性类FeignClientProperties
registerClientConfiguration()
chooseRoundRobinAfterFiltering
Feign接口=getBean()FeignClientFactoryBean.class
创建FeignClient 建造者,其中会根据context中的配置,设置Feign。如:日志等级、编解码器、契约,配置属性文件中的配置等。Feign.Builder builder = feign(context);
使用openFeign需在启动类上加@EnableFeignClients,从该注解开始
从服务列表中选择服务ILoadBalancer lb = getLoadBalancer(); Server svc = lb.chooseServer(loadBalancerKey);
添加配置builder.addConstructorArgValue(configuration);
扫描出带有@FeignClient注解的接口的beanDefinitionSet<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
lbClient(clientName)
创建Http连接默认配置属性类FeignHttpClientProperties
导入Gzip 解密器,默认未开启,开启需要配置,且不能用okhttp3连接@Import(DefaultGzipDecoderConfiguration.class)
Runnable wrapperRunnable = new Runnable()
loadBalance()
创建Feign客服端扫描器,可以扫描到标注有@FeignClient注解的接口ClassPathScanningCandidateComponentProvider scanner = getScanner();
invoke()
注册默认规范registry.registerBeanDefinition(name + \".\
call(Server server)
executeWithLoadBalancer
由于FeignClientsRegistrar继承ImportBeanDefinitionRegistrar,该类会在beanDefinition注册阶段实例化,并调用接口方法registerBeanDefinitions()拿到注册器,自定义注册beanDefinition
调用Feign接口ReflectiveFeign.FeignInvocationHandler.invoke()
注入所有FeignClient配置@Autowired(required = false)private List<FeignClientSpecification> configurations = new ArrayList<>();
handler
选择server策略,获取数组下标(第几个server)incrementAndGetModulo(eligible.size())
command.submit()
run()
执行构造方法
最后回调参数
restOfInit(clientConfig);
selectServer()
SynchronousMethodHandler = dispatch.get(method)返回类型dispatch.get(method).invoke(args)
updateAction.doUpdate();
集成了nacos,这里会调用nacos的获取实例方法
配置开启feign.compression.response.enabled = truefeign.compression.response.useGzipDecoder = true
feign.target(target);
代理方法被调用时,进入ReflectiveFeign.FeignInvocationHandler.invoke()方法return proxy;
枚举扫描包路径,扫描路径下的Feign接口for (String basePackage : basePackages)
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);
0 条评论
下一页