动态代理核心原理:JQuick-Java接口规则自动生成机制解析

动态代理核心原理:JQuick-Java接口规则自动生成机制解析

前言

JQuick-Java 最优雅的设计是「接口即契约,规则自动挂载」:Java 侧只定义一个接口,XML/内联规则按方法名自动绑定,createApi 一行生成可用代理------没有注解扫描、没有代码生成器、没有 Spring 依赖。这背后是接口动态代理的自动生成机制。本文从 JQuickJavaXmlParseFactory 与代理工厂源码出发,解析接口规则自动生成的核心原理。

核心技术原理

接口代理的装配链路:

  1. 规则解析 :JQuickJavaXmlParseFactory(xml 包)创建 XML 解析工厂,JQuickXmlParser.parse(xmlPath) 把 <javas namespace="接口全限定名"> 解析为 JQuickXmlNamespace,每个 <java> 成为一个 JQuickXmlMethod(含 name、returnClass、CDATA 内容);
  2. 代理生成 :JQuickXmlFactory.createApi(apiInterface) 基于 namespace 集合生成接口动态代理------内部为 JQuickAbsFactory 子类(XML 版 JQuickXmlFactory、内联版 JQuickInlineXmlFactory),持有 namespaceMap、context 与 JQuickXmlInvocationHandler;
  3. 调用分发 :代理方法被调用时,JQuickJavaXmlInvocationHandler 按方法名找到 JQuickXmlMethod,执行「参数绑定 → 函数定义解析 → 执行 → 返回转换」;
  4. 内联合并 :createApiInternal 把 rule() 注册的内联方法(tag = "inline")合并进对应 namespace,同名时内联覆盖 XML。

实战代码演示

1. 接口定义(无需任何注解约束方法名之外的额外配置)

java 复制代码
public interface UserMapper {
    int sum(@Param("a") int a, @Param("b") int b);
    int mul(@Param("a") int a, @Param("b") int b);
}

2. XML 规则(jquick-java.xml)

xml 复制代码
<javas namespace="com.github.paohaijiao.xml.UserMapper">
    <java name="sum" returnClass="java.util.List">
        <![CDATA[
            int def sum(int:a,int:b) {
                return a+b;
            }
        ]]>
    </java>
</javas>

3. 生成代理(三种入口殊途同归)

java 复制代码
// 方式一:统一入口(推荐)
UserMapper api1 = JQuickJava.create().createApi(UserMapper.class, "jquick-java.xml");

// 方式二:底层工厂
JQuickJavaXmlParseFactory handler = new JQuickJavaXmlParseFactory();
JQuickFactory factory = new JQuickXmlFactory(handler, "jquick-java.xml");
UserMapper api2 = factory.createApi(UserMapper.class);

// 方式三:纯内联(无 XML)
UserMapper api3 = JQuickJava.create()
        .rule("sum", "int def sum(int:a,int:b){ return a+b; }")
        .rule("mul", "int def mul(int:a,int:b){ return a*b; }")
        .createApi(UserMapper.class);

assertEquals(3, api1.sum(1, 2));
assertEquals(3, api2.sum(1, 2));
assertEquals(12, api3.mul(3, 4));

核心技术细节解析

  • namespace 即接口定位 :代理按 apiInterface.getName()(全限定名)在 namespaceMap 中查找规则;找不到 namespace 时,纯内联场景会动态创建(JQuickXmlBuilder.create().namespace(...))。
  • 方法名即规则名 :JQuickXmlMethod.setName(方法名),代理调用按方法名路由,无需额外映射配置。
  • 返回类型对齐 :JQuickValueTransformer 按 method.getReturnType() 转换执行结果,脚本返回类型与接口声明不一致时会运行期报错(好过静默错值)。
  • 上下文注入 :createApi 时入口的 JContext 与环境变量经 JQuickJavaRuntimeEnvironment 注入执行链,代理调用天然可读取入口注入的变量。

常见踩坑与解决方案

  1. 接口方法多参时 @Param 缺失 :参数绑定依赖 @Param 注解或参数名,缺失时绑定 null;务必为每个参数声明 @Param("名称")。
  2. namespace 与接口不匹配 :XML namespace 必须等于接口全限定名,否则代理调用找不到规则(方法返回 null 或抛异常)。
  3. 规则方法未定义 :接口方法在 XML 中没有同名 <java> 且无内联注册,调用时找不到 JQuickXmlMethod------请保证「接口方法 ⇔ 规则名」一一对应。

最佳实践

  • 优先使用 JQuickJava.createApi(...) 统一入口,底层工厂留给框架集成场景。
  • 接口方法与规则名严格对齐,命名即文档;必要时在接口注释中标注规则文件位置。
  • 代理实例复用(规则不变时不重建),解析与代理生成成本只在首次构建发生。

总结

JQuick-Java 的接口规则自动生成机制,用「namespace 定位 + 方法名路由 + 动态代理 + 参数/返回值对齐」四步,把「Java 接口 + 规则配置」无缝合成可调用的业务代理:零代码生成器、零扫描框架,规则即配置、代理即入口。对追求低侵入集成的团队,这是规则引擎落地的核心机制。

相关推荐
朝朝辞暮i3 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
leikooo4 小时前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust
言乐64 小时前
HTML视频审核模型
python·django·virtualenv·pygame·tornado
小师兄吃牛肉4 小时前
C语言篇:宏
c语言·开发语言
郑同学的笔记4 小时前
【c++随笔28】strcmp 和 memcmp对比
开发语言·c++
言乐65 小时前
Python根据无法识别搜索词找出可能输入内容模型
开发语言·python·django·virtualenv·pygame
weixin_307779135 小时前
有限产能智能排产与动态重排智能体:从需求解构到技术实现
开发语言·人工智能·算法·架构
Ivanqhz5 小时前
激活函数在 Transformer 中的作用及各种变体简述
java·linux·数据库·人工智能·深度学习
kakakahahahaha5 小时前
Windows C盘临时文件清理:%temp%、Windows Temp、Prefetch、Windows.old与hiberfil.sys处理指南
c语言·开发语言·windows
朝朝辞暮i5 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法