当前位置: 首页 > news >正文

[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.dtcms.com/a/314071.html

相关文章:

  • SparkSQL—sequence 函数用法详解
  • 无人机路径规划技术要点与难点分析
  • 权限管理命令
  • 【C++】2. 类和对象(上)
  • Anthropic 禁止 OpenAI 访问 Claude API:商业竞争与行业规范的冲突
  • mongodb源代码分析创建db流程分析
  • 芯脑觉醒:Deepoc如何让送餐机器人“活”起来?
  • 手搓TCP服务器实现基础IO
  • Go语言高并发价格监控系统设计
  • TCP 协议的“无消息边界”(No Message Boundaries)特性
  • sqli-labs-master/Less-31~Less-40
  • 内联函数:提升效率的空间换时间艺术
  • 移动端 WebView 视频无法播放怎么办 媒体控件错误排查与修复指南
  • 官宣!多功能DC-DC数字电源控制器重磅首发
  • 应用药品GSP证书识别技术,提升药品流通各环节的合规管理效率和风控水平
  • 数据工程与处理:AI时代的数据基石与智能化管道
  • java~final关键字
  • doris `unicode` 是多语言混合类型分词与elasticsearch分词差异
  • Java从入门到精通 - 算法、正则、异常
  • MQTT:安装部署
  • 【AI 加持下的 Python 编程实战 2_13】第九章:繁琐任务的自动化(中)——自动批量合并 PDF 文档
  • CMake进阶: 使用FetchContent方法基于gTest的C++单元测试
  • Docker-07.Docker基础-数据卷挂载
  • 在CAPL自动化脚本中巧用panel函数
  • 关键领域软件研发如何构建智能知识管理体系?从文档自动化到安全协同的全面升级
  • 实现Trie(前缀和)C++
  • 【REACT18.x】封装react-rouer实现多级路由嵌套,封装登录态权限拦截
  • PyTorch :三角函数与特殊运算
  • python:讲懂决策树,为理解随机森林算法做准备,以示例带学习,通俗易懂,容易理解和掌握
  • 张 事实关注增强模型:提升AI准确率新方法