[spring-cloud: NamedContextFactory ClientFactoryObjectProvider]-源码阅读

依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-commons</artifactId><version>4.3.0</version>
</dependency>

源码

NamedContextFactory

NamedContextFactory 类通过创建多个子上下文并为每个子上下文定义不同的配置,提供了灵活的 Spring 上下文管理方式。

/*** Creates a set of child contexts that allows a set of Specifications to define the beans* in each child context. Ported from spring-cloud-netflix FeignClientFactory and* SpringClientFactory** @param <C> specification* @author Spencer Gibb* @author Dave Syer* @author Tommy Karlsson* @author Olga Maciaszek-Sharma*/
public abstract class NamedContextFactory<C extends NamedContextFactory.Specification> implements DisposableBean, ApplicationContextAware {// 子容器初始化private final Map<String, ApplicationContextInitializer<GenericApplicationContext>> applicationContextInitializers;private final String propertySourceName;private final String propertyName;// 子容器集合private final Map<String, GenericApplicationContext> contexts = new ConcurrentHashMap<>();// 子容器配置private final Map<String, C> configurations = new ConcurrentHashMap<>();// 父容器private ApplicationContext parent;private final Class<?> defaultConfigType;public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName, String propertyName) {this(defaultConfigType, propertySourceName, propertyName, new HashMap<>());}public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName, String propertyName, Map<String, ApplicationContextInitializer<GenericApplicationContext>> applicationContextInitializers) {this.defaultConfigType = defaultConfigType;this.propertySourceName = propertySourceName;this.propertyName = propertyName;this.applicationContextInitializers = applicationContextInitializers;}@Overridepublic void setApplicationContext(ApplicationContext parent) throws BeansException {this.parent = parent;}public ApplicationContext getParent() {return parent;}public void setConfigurations(List<C> configurations) {for (C client : configurations) {this.configurations.put(client.getName(), client);}}public Set<String> getContextNames() {return new HashSet<>(this.contexts.keySet());}@Overridepublic void destroy() {Collection<GenericApplicationContext> values = this.contexts.values();for (GenericApplicationContext context : values) {// This can fail, but it never throws an exception (you see stack traces// logged as WARN).context.close();}this.contexts.clear();}protected GenericApplicationContext 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);}public GenericApplicationContext createContext(String name) {GenericApplicationContext context = buildContext(name);// there's an AOT initializer for this contextif (applicationContextInitializers.get(name) != null) {applicationContextInitializers.get(name).initialize(context);context.refresh();return context;}registerBeans(name, context);context.refresh();return context;}public void registerBeans(String name, GenericApplicationContext context) {Assert.isInstanceOf(AnnotationConfigRegistry.class, context);AnnotationConfigRegistry registry = (AnnotationConfigRegistry) context;if (this.configurations.containsKey(name)) {for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {registry.register(configuration);}}for (Map.Entry<String, C> entry : this.configurations.entrySet()) {if (entry.getKey().startsWith("default.")) {for (Class<?> configuration : entry.getValue().getConfiguration()) {registry.register(configuration);}}}registry.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);}// 根据指定名称创建并配置一个 GenericApplicationContext,并根据父上下文、AOT 支持等条件动态选择上下文实现。public GenericApplicationContext buildContext(String name) {// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101// https://github.com/spring-cloud/spring-cloud-openfeign/issues/475ClassLoader classLoader = getClass().getClassLoader();GenericApplicationContext context;if (this.parent != null) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();if (parent instanceof ConfigurableApplicationContext) {beanFactory.setBeanClassLoader(((ConfigurableApplicationContext) parent).getBeanFactory().getBeanClassLoader());}else {beanFactory.setBeanClassLoader(classLoader);}context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext(beanFactory) : new AnnotationConfigApplicationContext(beanFactory);}else {context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext() : new AnnotationConfigApplicationContext();}context.setClassLoader(classLoader);context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName, Collections.singletonMap(this.propertyName, name)));if (this.parent != null) {// Uses Environment from parent as well as beanscontext.setParent(this.parent);}context.setDisplayName(generateDisplayName(name));return context;}protected String generateDisplayName(String name) {return this.getClass().getSimpleName() + "-" + name;}public <T> T getInstance(String name, Class<T> type) {GenericApplicationContext context = getContext(name);try {return context.getBean(type);}catch (NoSuchBeanDefinitionException e) {// ignore}return null;}public <T> ObjectProvider<T> getLazyProvider(String name, Class<T> type) {return new ClientFactoryObjectProvider<>(this, name, type);}public <T> ObjectProvider<T> getProvider(String name, Class<T> type) {GenericApplicationContext context = getContext(name);return context.getBeanProvider(type);}public <T> T getInstance(String name, Class<?> clazz, Class<?>... generics) {ResolvableType type = ResolvableType.forClassWithGenerics(clazz, generics);return getInstance(name, type);}@SuppressWarnings("unchecked")public <T> T getInstance(String name, ResolvableType type) {GenericApplicationContext context = getContext(name);String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type);for (String beanName : beanNames) {if (context.isTypeMatch(beanName, type)) {return (T) context.getBean(beanName);}}return null;}@SuppressWarnings("unchecked")public <T> T getAnnotatedInstance(String name, ResolvableType type, Class<? extends Annotation> annotationType) {GenericApplicationContext context = getContext(name);String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(context, annotationType);List<T> beans = new ArrayList<>();for (String beanName : beanNames) {if (context.isTypeMatch(beanName, type)) {beans.add((T) context.getBean(beanName));}}if (beans.size() > 1) {throw new IllegalStateException("Only one annotated bean for type expected.");}return beans.isEmpty() ? null : beans.get(0);}public <T> Map<String, T> getInstances(String name, Class<T> type) {GenericApplicationContext context = getContext(name);return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);}public Map<String, C> getConfigurations() {return configurations;}/*** Specification with name and configuration.*/public interface Specification {String getName();Class<?>[] getConfiguration();}}

ClientFactoryObjectProvider

ClientFactoryObjectProvider 是一个特殊的 ObjectProvider,它通过延迟解析实际的 ObjectProvider,以便在创建命名的子上下文后再解析对象。

class ClientFactoryObjectProvider<T> implements ObjectProvider<T> {private final NamedContextFactory<?> clientFactory;private final String name;private final Class<T> type;private ObjectProvider<T> provider;ClientFactoryObjectProvider(NamedContextFactory<?> clientFactory, String name, Class<T> type) {this.clientFactory = clientFactory;this.name = name;this.type = type;}@Overridepublic T getObject(Object... args) throws BeansException {return delegate().getObject(args);}@Override@Nullablepublic T getIfAvailable() throws BeansException {return delegate().getIfAvailable();}@Overridepublic T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {return delegate().getIfAvailable(defaultSupplier);}@Overridepublic void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {delegate().ifAvailable(dependencyConsumer);}@Override@Nullablepublic T getIfUnique() throws BeansException {return delegate().getIfUnique();}@Overridepublic T getIfUnique(Supplier<T> defaultSupplier) throws BeansException {return delegate().getIfUnique(defaultSupplier);}@Overridepublic void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {delegate().ifUnique(dependencyConsumer);}@Overridepublic Iterator<T> iterator() {return delegate().iterator();}@Overridepublic Stream<T> stream() {return delegate().stream();}@Overridepublic T getObject() throws BeansException {return delegate().getObject();}@Overridepublic void forEach(Consumer<? super T> action) {delegate().forEach(action);}@Overridepublic Spliterator<T> spliterator() {return delegate().spliterator();}private ObjectProvider<T> delegate() {if (this.provider == null) {this.provider = this.clientFactory.getProvider(this.name, this.type);}return this.provider;}}

实现

推荐阅读:[spring-cloud: @LoadBalanced & @LoadBalancerClient]-源码分析

LoadBalancerClientFactory & LoadBalancerClientSpecification

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

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

相关文章

HBase MOB技术特点及使用场景介绍

在 HBase 2.0 版本之前,虽然 HBase 能够存储从 1 字节到 10MB 大小的二进制对象 ,但其读写路径主要针对小于 100KB 的值进行了优化。当面对大量大小在 100KB - 10MB 之间的数据时,传统的存储方式就会暴露出问题。例如,当存储大量的图片、文档或短视频等中等大小对象时,由于…

Ubuntu 配置密钥+密码登录

目录 1、密钥生成 2、发送公钥至 需要连接的服务器 3、选用私钥登录 1、密钥生成 ssh-keygen -t rsa -b 4096 -C "angindem"2、发送公钥至 需要连接的服务器 将.ssh中的id_rsa.pub 的密钥&#xff0c;放在authorized_keys中 注意&#xff1a;.ssh 文件夹一定赋予…

谷歌浏览器Chrome 缓存迁移

步骤 1&#xff1a;准备数据迁移1. 关闭 Chrome 及所有后台进程在任务管理器&#xff08;CtrlShiftEsc&#xff09;中结束所有 chrome.exe 进程。 2. 备份并移动原数据- 将 C:\Users\xxx\AppData\Local\Google\Chrome\User Data **整个文件夹**复制到新位置&#xff08;如 G:\…

Java中的RabbitMQ完全指南

Java中的RabbitMQ完全指南 1. 引言 什么是RabbitMQ RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;实现了高级消息队列协议&#xff08;AMQP&#xff09;。它充当应用程序之间的消息中间件&#xff0c;允许分布式系统中的不同组件进行异步通信。RabbitMQ使用Erlang语言…

【MCAL】AUTOSAR架构下SPI数据异步DMA收发具体实现

目录 前言 正文 1.依赖的硬件特性 1.1.SPI硬件特性 1.1.1. TXFIFO Single Move Mode 1.1.2. RXFIFO Single Move Mode 1.1.3. Move Counter模式 1.1.4. PT中断 1.2.IR硬件特性 1.3.DMA硬件特性 1.3.1. DMA通道硬件请求 1.3.2. DMA循环Buffer 1.3.3. DMA Link List …

【Unity】协程 Async

协程 协程是 Unity 内置的异步机制&#xff0c;通过 yield 暂停执行&#xff0c;实现任务在多帧中分段执行。与普通函数不同&#xff0c;协程可在执行过程中挂起和恢复&#xff0c;呈现"并发"效果&#xff0c;但本质上仍运行于主线程。若在协程中进行耗时操作&#…

《揭秘!10 分钟洞悉 Prompt、Function Calling、MCP 与 AI agent 奥秘》

Prompt、Function Calling、MCP、AI agent这些术语频繁闯入我们的视野&#xff0c;它们到底都是什么、有啥关系。只需十分钟&#xff0c;咱们抽丝剥茧&#xff0c;揭开它们的神秘面纱&#xff0c;轻松掌握这些关键概念 并了解AI agent 完整执行流程。 一、提示词&#xff08;P…

决策树(回归树)全解析:原理、实践与应用

文章目录一、概述1.1 介绍1.2 回归树和分类树区别二、重要参数、属性及接口2.1 criterion&#xff08;不纯度衡量指标&#xff09;2.2 回归树如何工作&#xff08;核心流程拆解&#xff09;三、用回归树拟合正弦曲线&#xff08;实战案例&#xff09;3.1 绘制正弦曲线3.2 为正弦…

【盘古100Pro+开发板实验例程】FPGA学习 | HDMI 回环实验

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 1. 实验简介 实验目的&#xff1a; 完成 HDMI 回环实验 实验环境&#xff1a; Window11 PDS2022.2-SP6.4 硬件环境…

鸿蒙系统PC安装指南

鸿蒙系统PC安装指南一、安装DevEco Studio集成开发环境二、下载鸿蒙系统PC三、启动鸿蒙系统及使用一、安装DevEco Studio集成开发环境首先访问华为官网上&#xff0c;注册并登录华为账号&#xff0c;以开始下载所需的软件。若尚未注册&#xff0c;请先注册一个。在官网页面中&a…

三十九、【扩展工具篇】Allpairspy 组合用例生成器:智能设计高效测试集

三十九、【扩展工具篇】Allpairspy 组合用例生成器:智能设计高效测试集 前言 准备工作 第一部分:后端实现 - `allpairspy` API 1. 创建 `allpairspy` 服务 2. 创建 `allpairspy` API 视图 3. 注册 API 路由 第二部分:前端实现 - `Allpairspy` 工具界面 1. 创建 API 服务 (`s…

ZooKeeper 深度实践:从原理到 Spring Boot 全栈落地

在 Kubernetes 为主流注册发现的今天&#xff0c;给出如何在 Spring Boot 中基于 ZooKeeper 实现服务注册/发现、分布式锁、配置中心以及集群协调的完整代码与最佳实践。所有示例均可直接复制运行。 1. ZooKeeper 架构与核心原理 1.1 角色 Leader&#xff1a;处理写请求&…

可验证随机函数-VRF

可验证随机函数&#xff08;Verifiable Random Function, VRF&#xff09;是一种结合密码学技术的伪随机数生成器&#xff0c;其核心特点是生成的随机数可被公开验证&#xff0c;且具有不可预测性和唯一性。以下是VRF的详细解析&#xff1a;1. 基本定义与核心特性 可验证性&…

极客大挑战2020(部分wp)

Roamphp1-Welcome 405请求方法不允许&#xff0c;改一下请求方法 数组绕过&#xff0c;在页面搜索flag即可&#xff01;本题&#xff1a;就是知道了405是请求方法不允许&#xff01; Roamphp2-Myblog&#xff08;zip协议加文件包含&#xff09; 首先进来就是一个博客页面&…

ESP32 外设驱动开发指南 (ESP-IDF框架)——GPIO篇:基础配置、外部中断与PWM(LEDC模块)应用

目录 一、前言 二、GPIO 2.1 GPIO简介 2.2 GPIO函数解析 2.3 LED驱动 2.4 KEY驱动 三、EXIT 3.1 EXIT简介 3.2 EXIT函数解析 3.3 EXIT驱动 四、LEDC 4.1 PWM原理解析 4.2 ESP32的LED PWM控制器介绍 4.3 LEDC函数解析 4.3.1 SW_PWM 4.3.2 HW_PWM 4.4 LEDC驱动 …

鸿蒙 ArkWeb 加载优化方案详解(2025 最佳实践)

适用平台&#xff1a;HarmonyOS NEXT / API 10 关键词&#xff1a;ArkWeb、WebviewController、NodeController、预加载、预连接、预渲染、性能优化一、前言&#xff1a;为什么必须优化 ArkWeb 加载&#xff1f;在鸿蒙生态中&#xff0c;ArkWeb 是系统级的 Web 容器引擎&#x…

JavaScript案例(乘法答题游戏)

项目概述 使用原生JavaScript实现一个乘法答题游戏&#xff0c;随机生成乘法题目&#xff0c;判断答案正误并记录分数&#xff0c;通过localStorage实现分数持久化存储。 核心功能需求 随机题目生成&#xff1a;动态生成1-10之间的乘法题答题交互&#xff1a;输入答案并提交…

EXCEL删除数据透视表

wps版 点击红框内任意区域 在顶部工具栏选择删除Excel 版 1.点击红框内任意区域2. 点击Enable Selection,再按住键盘上的Delete键&#xff0c;记住不是Backspace键

Python 飞机大战:从零开发经典 2D 射击游戏

引言&#xff1a;重温经典游戏开发 飞机大战作为经典的 2D 射击游戏&#xff0c;承载了许多人的童年回忆。使用 Python 和 Pygame 开发这样一款游戏不仅能重温经典&#xff0c;更是学习游戏开发绝佳的实践项目。本文将带你从零开始&#xff0c;一步步实现一个完整的飞机大战游…

Vue项目中实现浏览器串口通信:Web Serial API完整指南

前言 在现代Web开发中&#xff0c;随着IoT设备和硬件交互需求的增长&#xff0c;浏览器与串口设备的通信变得越来越重要。本文将详细介绍如何在Vue项目中使用Web Serial API实现串口通信功能&#xff0c;为开发者提供一个完整的解决方案。 技术背景 传统方案的局限性 传统的串口…