动态代理核心原理: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 接口 + 规则配置」无缝合成可调用的业务代理:零代码生成器、零扫描框架,规则即配置、代理即入口。对追求低侵入集成的团队,这是规则引擎落地的核心机制。

相关推荐
若亦_10 小时前
Java泛型入门:类型安全与上界约束
java·1024程序员节
凉茶钱10 小时前
stack、queue、priority_queue、容器适配器完整梳理
开发语言·c++·queue·1024程序员节·stack
编程的一拳超人10 小时前
【元宝搜索开发者征文大赛】四语实战:Java/Python/Go/Node.js 构建 AI 搜索应用全攻略
java·python·golang·node.js·agent
wuminyu10 小时前
JVM规范学习总结-Java源码经过javac编译后产物
java·linux·c语言·jvm·c++
fanruitian10 小时前
python anaconda jupyter notebook
python
ly768910 小时前
Spring Security 过滤器链定制:认证、CORS 与 CSRF 的先后顺序
java·spring boot·spring·spring security·csrf·cors·过滤器链
云和数据.ChenGuang10 小时前
Python 菜鸟入门:字典(dict)类型详解与 CRUD 实战案例
开发语言·人工智能·python
yuniko-n11 小时前
【JUC】读写锁 StampedLock
java·1024程序员节
小白今天也很酷11 小时前
MCXN947更新板载DAP_Link固件的方法
c语言·python·单片机·ubuntu·excel·1024程序员节
攻城狮Soar11 小时前
详解volatile
开发语言·c++·1024程序员节