微服务-@FeignClient 与 Feign 隔离

FeignClient 扫描

在这里插入图片描述
FeignClientsRegistrar#registerBeanDefinitions

public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {
// 注册默认配置
registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);
}

/**
*  默认配置描述如下* A custom <code>@Configuration</code> for all feign clients. Can contain override* <code>@Bean</code> definition for the pieces that make up the client, for instance* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.** @see FeignClientsConfiguration for the defaults* @return list of default configurations*/
Class<?>[] defaultConfiguration() default {};

FeignClientsRegistrar#registerFeignClients

ClassPathScanningCandidateComponentProvider scanner = getScanner();scanner.setResourceLoader(this.resourceLoader);scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));Set<String> basePackages = getBasePackages(metadata);for (String basePackage : basePackages) {// 获取候选类 被FeignClient标注			candidateComponents.addAll(scanner.findCandidateComponents(basePackage));}

FeignClientsRegistrar#registerClientConfiguration
FeignClientsRegistrar#registerFeignClient

// 这段逻辑会在真正获取对象的时候调用
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {factoryBean.setUrl(getUrl(beanFactory, attributes));factoryBean.setPath(getPath(beanFactory, attributes));factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));Object fallback = attributes.get("fallback");if (fallback != null) {factoryBean.setFallback(fallback instanceof Class? (Class<?>) fallback: ClassUtils.resolveClassName(fallback.toString(), null));}Object fallbackFactory = attributes.get("fallbackFactory");if (fallbackFactory != null) {factoryBean.setFallbackFactory(fallbackFactory instanceof Class? (Class<?>) fallbackFactory: ClassUtils.resolveClassName(fallbackFactory.toString(),null));}// 获取实例对象的核心逻辑return factoryBean.getObject();});definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);definition.setLazyInit(true);validate(attributes);

我们断点打在factoryBean.getObject() 追进去

return (T) loadBalance(builder, context,new HardCodedTarget<>(type, name, url));

然后继续往下走:HystrixTargeter -> Feign -> ReflectiveFeign

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);// JDK 动态代理创建了真正的对象  handler类为HystrixInvocationHandler implements InvocationHandlerT proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),new Class<?>[] {target.type()}, handler);for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {defaultMethodHandler.bindTo(proxy);}return proxy;}

调用的时候

 HystrixCommand<Object> hystrixCommand =new HystrixCommand<Object>(setterMethodMap.get(method)) {@Overrideprotected Object run() throws Exception {try {// 这里真正的去调用远程方法return HystrixInvocationHandler.this.dispatch.get(method).invoke(args);} catch (Exception e) {throw e;} catch (Throwable t) {throw (Error) t;}}// 这里是异常处理@Overrideprotected Object getFallback() {if (fallbackFactory == null) {return super.getFallback();}try {Object fallback = fallbackFactory.create(getExecutionException());Object result = fallbackMethodMap.get(method).invoke(fallback, args);if (isReturnsHystrixCommand(method)) {return ((HystrixCommand) result).execute();} else if (isReturnsObservable(method)) {// Create a cold Observablereturn ((Observable) result).toBlocking().first();} else if (isReturnsSingle(method)) {// Create a cold Observable as a Singlereturn ((Single) result).toObservable().toBlocking().first();} else if (isReturnsCompletable(method)) {((Completable) result).await();return null;} else if (isReturnsCompletableFuture(method)) {return ((Future) result).get();} else {return result;}} catch (IllegalAccessException e) {// shouldn't happen as method is public due to being an interfacethrow new AssertionError(e);} catch (InvocationTargetException | ExecutionException e) {// Exceptions on fallback are tossed by Hystrixthrow new AssertionError(e.getCause());} catch (InterruptedException e) {// Exceptions on fallback are tossed by HystrixThread.currentThread().interrupt();throw new AssertionError(e.getCause());}}};

在这里插入图片描述
我们在调用的时候在选择实例NacosNamingService#selectInstances,发现会选择实例,这就是 OpenFeign 首次发起远程调用时,会很慢的原因。
在这里插入图片描述

Feign 隔离

在这里插入图片描述
源代码
org.springframework.cloud.openfeign.FeignClientFactoryBean#get

org.springframework.cloud.context.named.NamedContextFactory#getInstance

public <T> T getInstance(String name, Class<T> type) {AnnotationConfigApplicationContext context = getContext(name);try {return context.getBean(type);}catch (NoSuchBeanDefinitionException e) {// ignore}return null;
}

org.springframework.cloud.context.named.NamedContextFactory#getContext

protected AnnotationConfigApplicationContext getContext(String name) {if (!this.contexts.containsKey(name)) {synchronized (this.contexts) {if (!this.contexts.containsKey(name)) {this.contexts.put(name, createContext(name));}}}return this.contexts.get(name);
}

org.springframework.cloud.context.named.NamedContextFactory#createContext

protected AnnotationConfigApplicationContext createContext(String name) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();if (this.configurations.containsKey(name)) {for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {context.register(configuration);}}for (Map.Entry<String, C> entry : this.configurations.entrySet()) {if (entry.getKey().startsWith("default.")) {for (Class<?> configuration : entry.getValue().getConfiguration()) {context.register(configuration);}}}context.register(PropertyPlaceholderAutoConfiguration.class,this.defaultConfigType);context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName,Collections.<String, Object>singletonMap(this.propertyName, name)));if (this.parent != null) {// Uses Environment from parent as well as beanscontext.setParent(this.parent);// jdk11 issue// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101context.setClassLoader(this.parent.getClassLoader());}context.setDisplayName(generateDisplayName(name));// 重点在这里,创建了一个迷你的上下文对象,并且刷新了迷你上下文对象进行实例化操作 这会影响OpenFeing的效率变慢context.refresh();return context;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/317188.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是差值表达式

在Vue.js中&#xff0c;差值表达式是一种基本的数据绑定形式&#xff0c;用于将数据绑定到文档对象模型&#xff08;DOM&#xff09;上。差值表达式通常使用双大括号 {{ }} 来表示&#xff0c;这种语法非常直观。当Vue实例的数据发生变化时&#xff0c;差值表达式的内容也会相应…

八大算法排序@希尔排序(C语言版本)

目录 希尔排序概念算法思想示例分析结论算法步骤选择增量序列按增量分组逐步缩小增量 算法优势 代码实现核心算法希尔排序代码实现&#xff1a; 时间复杂度空间复杂度特性总结 该排序会关联到直接插入排序的知识点&#xff0c;如果对于直接插入排序还有所疑惑&#xff0c;可以跳…

数据结构学习 jz42连续子数组最大和

关键词&#xff1a;动态规划 滚动数组 最长上升子序列 这道题比较简单&#xff0c;类似最长上升子序列&#xff0c;比最长上升子序列简单。 和最长上升子序列的区别&#xff1a;这道题因为是连续的&#xff0c;所以只用记录max就好了。最长上升子序列是不连续的&#xff0c;所…

FA发放云桌面并与FC对接

&#xff08;7&#xff09;分配桌面&#xff08;该组为刚刚创建的域名用户和组&#xff09;&#xff0c;确认无误&#xff0c;直接发放 &#xff08;8&#xff09;可在任务中心查看发放的进度 3、FA的登录流程 &#xff08;1&#xff09;登录WI&#xff1a;客户端访问VLB&…

网络安全B模块(笔记详解)- 数字取证

数据分析数字取证-attack 1.使用Wireshark查看并分析Windows 7桌面下的attack.pcapng数据包文件,通过分析数据包attack.pcapng找出恶意用户的IP地址,并将恶意用户的IP地址作为Flag(形式:[IP地址])提交; 解析:http.request.method==POST ​ Flag:[172.16.1.102] 2.继续…

国图公考:公务员政审阶段,这四类家庭不予通过!

公务员考试需要经过笔试、面试、体检、政审等步骤&#xff0c;全部合格之后才能成为一名公务员&#xff0c;其中政审的要求是非常严格的&#xff0c;如果你是以下四类家庭的孩子&#xff0c;政审是不通过的。 1. 配偶、直系亲属和三代以内旁系亲属因参与民族、宗教、非法宗教、…

vue3项目创建

安装node.js vue --version &#xff08;4.5.0以上&#xff09; npm install -g vue/cli vue create 项目名称 npm run dev 启动 npm run build 打包 ———————— vite 创建工程 npm create vuelatest npm i npm run dev 启动 npm run build 打包 项目结构…

wordpress在界面将站点地址直接修改为https导致上不去问题的解决办法

wordpress在界面将站点地址直接修改为https导致上不去问题的解决办法 #修改数据库yz_options

理解UML中的依赖关系

理解UML中的依赖关系 在面向对象的设计中&#xff0c;理解各种类之间的关系对于构建一个清晰、可维护的系统至关重要。UML&#xff08;统一建模语言&#xff09;为我们提供了一种可视化这些关系的方式。今天&#xff0c;我们将深入探讨UML中的依赖关系&#xff08;Dependency&a…

中科驭数鄢贵海新年演讲:数字经济下的算力基础先行,DPU自主创新力量大有可为

近日&#xff0c;中科驭数创始人、CEO鄢贵海受邀在北京电视台《金融街午餐会》新年特别活动中发表新年演讲。 鄢贵海在新年演讲中提到&#xff0c;在21世纪头30年&#xff0c;我们不可思议地经历了三次重要的科技变革&#xff0c;分别是互联网的普及、移动互联网的崛起、以及人…

一种可扩展的多属性可控文本生成即插即用方法

《An extensible plug-and-play method for multi-aspect controllable text generation》论文解读 文章的主要工作 &#xff08;1&#xff09;提出了一种可扩展的即插即用方法&#xff0c;PROMPT GATING&#xff0c;用于多方面可控文本生成&#xff0c;它能够通过简单地连接…

AI的突破与融合:2024年中国智能技术的新纪元_光点科技

随着人工智能领域的不断突破&#xff0c;2024年注定将成为中国智能技术发展的一个新纪元。当下&#xff0c;AI技术不仅在理论研究上取得了重大进展&#xff0c;其在商业应用、社会服务等领域的融合也日益深入。本文将结合近期网络上的AI热点&#xff0c;展望中国在AI技术方面的…