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

按DDD领域分析Openfeign

按DDD领域分析Openfeign

请关注微信公众号:阿呆-bot

1. 入口类及说明

1.1 入口类:Feign 和 ReflectiveFeign

Feign 是抽象工厂类,ReflectiveFeign 是其基于反射的实现,负责创建 HTTP API 代理实例。

public abstract class Feign {public static Builder builder() {return new Builder();}public abstract <T> T newInstance(Target<T> target);
}public class ReflectiveFeign<C> extends Feign {public <T> T newInstance(Target<T> target) {Map<Method, MethodHandler> methodToHandler = targetToHandlersByName.apply(target, requestContext);InvocationHandler handler = factory.create(target, methodToHandler);return (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[] {target.type()}, handler);}
}

2. DDD 业务域划分

Core 模块可以划分为以下业务域:

2.1 契约域(Contract Domain)

职责: 解析接口方法上的注解,生成方法元数据。

核心类:

  • Contract: 契约接口
  • BaseContract: 基础契约实现
  • DeclarativeContract: 声明式契约基类
  • Contract.Default: 默认契约实现
  • MethodMetadata: 方法元数据

领域边界: 负责将 Java 接口方法转换为 HTTP 请求元数据,不涉及实际的 HTTP 请求执行。

PlantUML 类关系图

image.png

2.2 方法处理域(MethodHandler Domain)

职责: 处理接口方法的调用,执行 HTTP 请求并解码响应。

核心类:

  • MethodHandler: 方法处理器接口
  • SynchronousMethodHandler: 同步方法处理器
  • AsynchronousMethodHandler: 异步方法处理器
  • DefaultMethodHandler: 默认方法处理器(处理接口默认方法)
  • MethodHandlerConfiguration: 方法处理器配置

领域边界: 负责方法调用的执行流程,包括请求构建、HTTP 执行、响应处理,但不涉及注解解析。

PlantUML 类关系图

image.png

2.3 客户端域(Client Domain)

职责: 执行实际的 HTTP 请求,是 Feign 与底层 HTTP 库的抽象。

核心类:

  • Client: HTTP 客户端接口
  • Client.Default: 默认实现(基于 HttpURLConnection)
  • AsyncClient: 异步客户端接口

领域边界: 负责 HTTP 请求的执行,不涉及请求构建和响应解码。

PlantUML 类关系图

image.png

2.4 编解码域(Encoder/Decoder Domain)

职责: 将 Java 对象编码为 HTTP 请求体,将 HTTP 响应体解码为 Java 对象。

核心类:

  • Encoder: 编码器接口
  • Encoder.Default: 默认编码器
  • Decoder: 解码器接口
  • Decoder.Default: 默认解码器
  • ErrorDecoder: 错误解码器接口

领域边界: 负责对象序列化和反序列化,不涉及 HTTP 传输。

PlantUML 类关系图

image.png

2.5 目标域(Target Domain)

职责: 表示要调用的远程 HTTP 服务,包含服务类型、名称和基础 URL。

核心类:

  • Target: 目标接口
  • Target.HardCodedTarget: 硬编码目标实现
  • Target.EmptyTarget: 空目标实现

领域边界: 负责目标服务的表示和请求模板的应用,不涉及具体的 HTTP 请求执行。

PlantUML 类关系图

image.png

2.6 请求模板域(RequestTemplate Domain)

职责: 构建 HTTP 请求模板,支持 URI 模板表达式和参数替换。

核心类:

  • RequestTemplate: 请求模板类
  • RequestTemplate.Factory: 请求模板工厂接口(内部接口)
  • RequestTemplateFactoryResolver: 请求模板工厂解析器
  • template.UriTemplate: URI 模板
  • template.BodyTemplate: 请求体模板
  • template.HeaderTemplate: 请求头模板
  • template.QueryTemplate: 查询参数模板

领域边界: 负责请求模板的构建和参数替换,不涉及实际的 HTTP 请求发送。

PlantUML 类关系图

image.png

3. 领域间关系

3.1 领域协作流程

各业务域通过以下方式协作:

  1. 契约域方法处理域: Contract 解析注解生成 MethodMetadata,MethodHandler 使用 MethodMetadata 构建请求
  2. 方法处理域请求模板域: MethodHandler 使用 RequestTemplateFactory 创建请求模板
  3. 方法处理域客户端域: MethodHandler 调用 Client 执行 HTTP 请求
  4. 方法处理域编解码域: MethodHandler 使用 Encoder 编码请求体,使用 Decoder 解码响应体
  5. 方法处理域目标域: MethodHandler 使用 Target 应用请求模板

PlantUML 时序图:方法调用流程

image.png

4. 关键代码片段

4.1 Contract 解析方法元数据

protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {final MethodMetadata data = new MethodMetadata();data.targetType(targetType);data.method(method);data.returnType(Types.resolve(targetType, targetType, method.getGenericReturnType()));data.configKey(Feign.configKey(targetType, method));processAnnotationOnClass(data, targetType);for (final Annotation methodAnnotation : method.getAnnotations()) {processAnnotationOnMethod(data, methodAnnotation, method);}// 处理参数注解for (int i = 0; i < parameterAnnotations.length; i++) {processAnnotationsOnParameter(data, parameterAnnotations[i], i);}return data;
}

4.2 SynchronousMethodHandler 执行请求

public Object invoke(Object[] argv) throws Throwable {RequestTemplate template = methodHandlerConfiguration.getBuildTemplateFromArgs().create(argv);Options options = findOptions(argv);Retryer retryer = this.methodHandlerConfiguration.getRetryer().clone();while (true) {try {return executeAndDecode(template, options);} catch (RetryableException e) {retryer.continueOrPropagate(e);continue;}}
}Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {Request request = targetRequest(template);Response response = client.execute(request, options);return responseHandler.handleResponse(methodHandlerConfiguration.getMetadata().configKey(), response,methodHandlerConfiguration.getMetadata().returnType(), elapsedTime);
}

4.3 RequestTemplate 参数解析

public RequestTemplate resolve(Map<String, Object> variables) {if (variables == null || variables.isEmpty()) {return this;}RequestTemplate resolved = new RequestTemplate(this);if (uriTemplate != null) {resolved.uriTemplate = uriTemplate.expand(variables);}// 解析查询参数for (Map.Entry<String, QueryTemplate> entry : queries.entrySet()) {resolved.queries.put(entry.getKey(), entry.getValue().expand(variables));}// 解析请求头for (Map.Entry<String, HeaderTemplate> entry : headers.entrySet()) {resolved.headers.put(entry.getKey(), entry.getValue().expand(variables));}return resolved;
}

5. 实现关键点说明

5.1 领域驱动设计原则

Core 模块通过以下方式体现 DDD 原则:

  1. 领域边界清晰: 每个业务域职责单一,边界明确
  2. 领域模型: 每个域都有核心实体(如 Contract、MethodHandler、Client)
  3. 领域服务: 通过接口定义领域服务,支持可插拔实现
  4. 聚合根: Feign 和 ReflectiveFeign 作为聚合根,协调各领域协作

5.2 依赖倒置

各领域通过接口交互,实现依赖倒置:

  • MethodHandler 依赖 Client 接口,而非具体实现
  • Contract 生成 MethodMetadata,MethodHandler 使用 MethodMetadata
  • Encoder/Decoder 通过接口注入,支持替换

5.3 策略模式应用

各领域大量使用策略模式:

  • Contract: 支持不同的注解解析策略(Default、JAX-RS、Spring)
  • Client: 支持不同的 HTTP 客户端实现(Default、OkHttp、Apache HttpClient)
  • Encoder/Decoder: 支持不同的序列化策略(Default、Jackson、Gson)

5.4 模板方法模式

RequestTemplate 使用模板方法模式:

  • 定义请求模板结构(URI、Headers、Query、Body)
  • 支持参数替换和展开
  • 最终生成完整的 Request 对象

5.5 工厂模式

多处使用工厂模式:

  • Feign.builder(): 创建 Builder 工厂
  • MethodHandler.Factory: 创建 MethodHandler
  • RequestTemplateFactory: 创建 RequestTemplate(RequestTemplate.Factory 的内部接口)

6. 总结说明

Core 模块通过 DDD 领域划分,实现了清晰的职责分离:

  1. 契约域: 负责注解解析和元数据生成,是 Feign 声明式编程的基础
  2. 方法处理域: 负责方法调用的执行,是 Feign 的核心执行引擎
  3. 客户端域: 负责 HTTP 请求执行,是 Feign 与底层 HTTP 库的抽象
  4. 编解码域: 负责对象序列化,支持多种序列化框架
  5. 目标域: 负责目标服务表示,支持动态目标配置
  6. 请求模板域: 负责请求构建,支持灵活的 URI 模板和参数替换

各领域通过清晰的接口协作,实现了高内聚、低耦合的架构设计。这种设计使得 Feign 既灵活又可扩展,支持多种集成场景。

http://www.jsqmd.com/news/71238/

相关文章:

  • Python threading.Lock() thread lambda
  • Python 面向对象编程 (OOP) 核心:类、封装与继承
  • 12/10
  • 完整教程:分享一个基于服务端地图服务裁剪的方法
  • Nginx安全配置
  • 并发编程的三大基石:从底层逻辑聊透“同步、互斥与分工”
  • 个人电脑本地私有知识库解决方案:访答知识库全面解析
  • 【Agent】MemOS 源码笔记---(4)---KV Cache
  • 2025.12.10
  • 大数据存储新范式:RustFS与Hadoop生态无缝集成实战指南
  • Ai元人文构想:黑箱之渡,白箱之锚——大行为模型践行意义行为原生
  • 在 .Net 8 WEBAPI 中实现实体框架的 Code First 办法
  • 60
  • Coppersmith 学习笔记
  • python —— 树的遍历 —— 深度优先遍历(先序、中序、后序) —— 非递归方式(使用栈数据结构进行辅助)
  • 【SQL技术】不同数据库引擎 SQL 优化方案剖析 - 详解
  • IntelliJ IDEA 最常用的快捷键
  • C++ 循环结构:控制程序重复执行的核心机制 - 教程
  • ASP.NET 实战:用 CSS 选择器打造一个可搜索、响应式的书籍管理系统 - 教程
  • Python list all files in dir recursivelly
  • python —— 树的遍历 —— 深度优先遍历(先序、中序、后序)
  • springAI集成智谱--流式输出
  • python —— 满二叉树的广度优先遍历
  • 切比雪夫多项式与数值最优化算法收敛率的关系
  • 恰好被k个区间覆盖的点的数量
  • Day59(29)-F:\vs_ai_work\vue-tlias-management
  • windriver 第5章:USB 概述
  • Airflow - from airflow import DAG and from airflow.sdk import DAG, which one is better?
  • langchain工具上下文
  • 货代邮件自动化处理系统设计文档