使用 RelProxy for Java 提高生产力

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

RelProxy 的目的是通过两种非排他性的方式丰富您的开发体验:

  • 能够在生产中修改用户代码而无需重新加载整个应用程序。

  • 提高开发时间的生产力,避免耗时的应用程序重新加载,同时对生产性能影响为零。

这两个目标在某些情况下都可以实现,通常在注册应用程序所需的典型侦听器/回调时,只需向应用程序添加一些 RelProxy 代码即可。这是“侵入式”的方式。

如果您是 Java 框架或一般自治 Java 服务模块的开发人员,则可以在您的框架中内置 RelProxy Java,以透明地为使用您的框架的最终用户代码提供代码自动重载,而无需在您的框架中显式使用 RelProxy API超出某些必需配置的用户代码。

有两种 API 可以使用 RelProxy 的 Java 部分:

  1. JProxy类及相关:主要是静态方法
  2. Java Scripting API:基于接口

第二种选择是将 RelProxy Java 嵌入到您的 Java 框架中,因为它基于接口,不需要在您的 API 中公开 RelProxy 的公共类,因为引导程序可以在您的框架中执行。我们将使用 JProxyScriptEngineFactory.create() 的简化版 API。

JProxyScriptEngine 旨在提供与 JProxy 相同的功能,即相同的方法,但在这种情况下使用纯接口。

一个简单的示例是展示如何嵌入 RelProxy 的最佳方式,这个示例 RelProxyBuiltin(项目 relproxy_builtin_ex)包含在 RelProxy 示例存储库中。它定义了两个由最终用户代码实现和注册的侦听器,一个侦听器用于显示选项,另一个用于执行相应的选定操作。

这个迷你框架和使用示例是使用 NetBeans 和 Maven 开发的。

有两个包:

  1. com.innowhere.relproxy_builtin_ex :迷你框架。子包 com.innowhere.relproxy_builtin_ex.impl 包含框架的唯一非公共类。
  2. com.innowhere.relproxy_builtin_ex_main :一个简单的使用示例。

迷你框架(公共类和接口):

RelProxyBuiltinRoot.java


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


RelProxyBuiltin.java


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


输出监听器.java


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


命令监听器.java


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


现在是实现细节,这个类展示了内置 RelProxy 是多么简单:

RelProxyBuiltinImpl.java


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


这三种方法足以解释如何引导 RelProxy Java 引擎以及检测注册热重载的侦听器有多么容易:

RelProxyBuiltinImpl.java(部分)


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


必须在启动时调用公共方法 RelProxyBuiltin.getJProxyScriptEngine() 来配置 RelProxy。如果未配置和启用 RelProxy,则不会影响性能。


请记住,由 create(…) 方法返回的代理对象正确地调用了内部真实侦听器对象中的方法 hashCode() equals(Object) ,以实现侦听器集合/注册表所需的标识目的。

这是这个基于控制台的程序的示例代码(名称受 JUnit 启发,但并不是真正的 JUnit 测试示例):

主.java


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


看看这段代码:

Main.java(部分)


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


我们获取并稍后注册我们应用程序源代码的根文件夹,此代码“可能”可重新加载。

我们需要排除框架的源代码,因为显然不是最终用户代码(不可重新加载),而包含测试代码的 Main.java 文件,此类不可重新加载,只有类 TestListener.java (在同一文件夹中比 Main.java) 将(并且必须)可重新加载。我们可以简化这个 isExcluded 方法,只排除与文件 TestListener.java 不同的任何内容,但建议排除整个文件夹以加快源代码文件树的遍历,否则所有不可重新加载的文件都会被检查到不可重新加载的文件夹中。

最后,包含两个侦听器的类 TestListener.java ,实现的 CommandListener 被强制成为一个匿名内部类,仅用于演示目的:

测试监听器.java


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


执行 Main 类并尝试预定义的选项。要检查 RelProxy 是否工作正常,请尝试在不停止程序的情况下添加一个新选项“same”:


 package com.innowhere.relproxy_builtin_ex;

import com.innowhere.relproxy_builtin_ex.impl.RelProxyBuiltinImpl;

public class RelProxyBuiltinRoot { private final static RelProxyBuiltinImpl SINGLETON = new RelProxyBuiltinImpl();

public static RelProxyBuiltin get()
{
    return SINGLETON;
}

}


下一个要处理的短语现在包括无需停止控制台应用程序的“相同”操作。

ItsNat web 框架可能是第一个包含使用此技术的 RelProxy 的框架(从 v1.4 开始)。

注意:使用RelProxy 0.8.7或更高版本,此版本增加了通过这种方式嵌入时的改进。