关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »使用 RelProxy 提高 Java 开发效率

    使用 RelProxy 提高 Java 开发效率

    2015-10-31 00:00:00 出处:segmentfault
    分享

    微信扫一扫:分享

    Scan me!

    微信里点“发现”,扫一下

    二维码便可将本文分享至朋友圈。

    RelProxy 旨在通过下列两种方式提高开发效率:

    可以在生产环境下修改用户代码,而不需要重新加载整个应用。

    提高开发效率,避免花费过多的时间加载应用且对性能不会有影响。

    两个目标都要求在你的应用中增加一些 RelProxy 代码,注册成一种典型的监听、回调模式。这是一种“侵入”的方式。

    如果你是一名Java 框架或独立 Java 通用服务模块的开发者,可以将 RelProxy Java 嵌入到你的框架中,这样能透明地为框架的终端用户提供代码自动加载功能,只需要进行一些必要的配置,而无需调用 RelProxy API。

    对使用 Java 版的 RelProxy,有两种 API 可供调用:

    JProxy 及其相关类:主要是静态方法

    Java 脚本 API:基于接口

    第二种方式更适合将 RelProxy 嵌入到你的 Java 框架中,这种方式是基于接口的,在你的 API 中无需暴露公共 RelProxy 类,因为在框架中会执行启动程序。我将使用比较简单的 API:JProxyScriptEngineFactory.create()。

    JProxyScriptEngine 的功能与 Jproxy 相同,也就是说具有相同的方法。只是这种情况下,只需要使用接口。

    一个简单的例子是演示如何嵌入 RelProxy 的最好方式。这个例子是 RelProxy 的示例仓库中包含的 RelProxyBuiltin(relproxy_builtin_ex 项目中)。它定义了两个监听器来实现注册用户端的代码,一个监听器显示选项(option),另一个执行选择的行为。

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

    有两个包:

    com.innowhere.relproxy_builtin_ex :迷你框架。子包 com.innowhere.relproxy_builtin_ex.impl 只包含一个非公共的类。

    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.jproxy.JProxyScriptEngine;
    import java.io.InputStream;
    import java.io.PrintStream;
    public interface RelProxyBuiltin
    {
        public JProxyScriptEngine getJProxyScriptEngine();
        public void addOutputListener(OutputListener listener);
        public void removeOutputListener(OutputListener listener);
        public int getOutputListenerCount();
        public void addCommandListener(CommandListener listener);
        public void removeCommandListener(CommandListener listener);
        public int getCommandListenerCount();
        public void runLoop(InputStream in,PrintStream out);
    }

    OutputListener.java

    package com.innowhere.relproxy_builtin_ex;
    import java.io.PrintStream;
    public interface OutputListener
    {
        public void write(PrintStream out);
    }

    CommandListener.java

    package com.innowhere.relproxy_builtin_ex;
    import java.io.PrintStream;
    public interface CommandListener
    {
        public void execute(String command,String input,PrintStream out);
    }

    现在看一下实现细节,该类演示了怎样简单地内嵌 RelProxy:

    RelProxyBuiltinImpl.java

    package com.innowhere.relproxy_builtin_ex.impl;
    import com.innowhere.relproxy.jproxy.JProxyScriptEngine;
    import com.innowhere.relproxy.jproxy.JProxyScriptEngineFactory;
    import com.innowhere.relproxy_builtin_ex.CommandListener;
    import com.innowhere.relproxy_builtin_ex.OutputListener;
    import com.innowhere.relproxy_builtin_ex.RelProxyBuiltin;
    import java.io.InputStream;
    import java.io.PrintStream;
    import java.util.LinkedHashSet;
    import java.util.Scanner;
    public class RelProxyBuiltinImpl implements RelProxyBuiltin
    {
        protected JProxyScriptEngine jProxyEngine = null;
        protected LinkedHashSet<OutputListener> outListeners = new LinkedHashSet<OutputListener>();
        protected LinkedHashSet<CommandListener>  commandListeners = new LinkedHashSet<CommandListener>();
        @Override
        public JProxyScriptEngine getJProxyScriptEngine()
        {
            if (jProxyEngine == null) jProxyEngine = (JProxyScriptEngine)JProxyScriptEngineFactory.create().getScriptEngine();
            return jProxyEngine;
        }
        public JProxyScriptEngine getJProxyScriptEngineIfConfigured()
        {
            if (jProxyEngine == null || !jProxyEngine.isEnabled())
                return null;
            return jProxyEngine;
        }
        @Override
        public void addOutputListener(OutputListener listener)
        {
            JProxyScriptEngine jProxy = getJProxyScriptEngineIfConfigured();
            if (jProxy != null)
            {
                listener = jProxy.create(listener,OutputListener.class);
            }
            outListeners.add(listener);
        }
        @Override
        public void removeOutputListener(OutputListener listener)
        {
            JProxyScriptEngine jProxy = getJProxyScriptEngineIfConfigured();
            if (jProxy != null)
            {
                listener = jProxy.create(listener,OutputListener.class);
            }
            outListeners.remove(listener);
        }
        @Override
        public int getOutputListenerCount()
        {
            return outListeners.size();
        }
        @Override
        public void addCommandListener(CommandListener listener)
        {
            JProxyScriptEngine jProxy = getJProxyScriptEngineIfConfigured();
            if (jProxy != null)
            {
                listener = jProxy.create(listener,CommandListener.class);
            }
            commandListeners.add(listener);
        }
        @Override
        public void removeCommandListener(CommandListener listener)
        {
            JProxyScriptEngine jProxy = getJProxyScriptEngineIfConfigured();
            if (jProxy != null)
            {
                listener = jProxy.create(listener,CommandListener.class);
            }
            commandListeners.remove(listener);
        }
        @Override
        public int getCommandListenerCount()
        {
            return commandListeners.size();
        }
        @Override
        public void runLoop(InputStream in,PrintStream out)
        {
            Scanner scanner = new Scanner(in);
            while(true)
            {
                out.print("Enter phrase:");
                String input = scanner.nextLine();
                out.println("Command list:");
                for(OutputListener listener : outListeners)
                    listener.write(out);
                out.print("Enter command (or quit):");
                String command = scanner.nextLine();
                if ("quit".equals(command))
                    break;
                for(CommandListener listener : commandListeners)
                    listener.execute(command,input,out);
            }
        }
    }

    这三个方法足以解释怎样启动 RelProxy Java 引擎,怎样简单地使用指令监听器来注册热加载。

    RelProxyBuiltinImpl.java (部分)

      @Override
        public JProxyScriptEngine getJProxyScriptEngine()
        {
            if (jProxyEngine == null) jProxyEngine = (JProxyScriptEngine)JProxyScriptEngineFactory.create().getScriptEngine();
            return jProxyEngine;
        }
        public JProxyScriptEngine getJProxyScriptEngineIfConfigured()
        {
            if (jProxyEngine == null || !jProxyEngine.isEnabled())
                return null;
            return jProxyEngine;
        }
        @Override
        public void addOutputListener(OutputListener listener)
        {
            JProxyScriptEngine jProxy = getJProxyScriptEngineIfConfigured();
            if (jProxy != null)
            {
                listener = jProxy.create(listener,OutputListener.class);
            }
            outListeners.add(listener);
        }

    公共方法 RelProxyBuiltin.getJProxyScriptEngine() 必须在启动时执行,用于配置 RelProxy。如果没有配置,RelProxy 就不起作用。

    请记住,通过 create(…) 创建的代理对象需要能正确的执行 hashCode() 方法和 equals(Object) 方法,监听器集合、监听记录依赖这两个方法来区别监听器对象。

    这是基于控制台的示例代码(名称与 JUnit 类似,但确实不是 JUnit 的测试示例):

    Main.java

    package com.innowhere.relproxy_builtin_ex_main;
    import com.innowhere.relproxy.RelProxyOnReloadListener;
    import com.innowhere.relproxy.jproxy.JProxy;
    import com.innowhere.relproxy.jproxy.JProxyCompilerListener;
    import com.innowhere.relproxy.jproxy.JProxyConfig;
    import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener;
    import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener;
    import com.innowhere.relproxy.jproxy.JProxyScriptEngine;
    import com.innowhere.relproxy_builtin_ex.CommandListener;
    import com.innowhere.relproxy_builtin_ex.RelProxyBuiltin;
    import com.innowhere.relproxy_builtin_ex.RelProxyBuiltinRoot;
    import java.io.File;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.util.Arrays;
    import java.util.List;
    import javax.tools.Diagnostic;
    import javax.tools.DiagnosticCollector;
    import javax.tools.JavaFileObject;
    public class Main
    {
        public static void main(String[] args) throws Exception
        {
            new Main();
        }
        public Main()
        {
            // Note: NetBeans Console window works bad (no input) with Maven Test tasks http://stackoverflow.com/questions/3035351/broken-console-in-maven-project-using-netbeans
            // this is why is not a really JUnit test.
            setUp();
            try
            {
                mainTest();
            }
            finally
            {
                tearDown();
            }
            System.exit(0);
        }
        public void setUp()
        {
            URL res = this.getClass().getResource("/"); // .../target/classes/
            // Use example of RelProxy in development time:
            String inputPath = res.getFile() + "/../../src/main/java/";
            if (new File(inputPath).exists())
            {
                System.out.println("RelProxy to be enabled, development mode detected");
            }
            else
            {
                System.out.println("RelProxy disabled, production mode detected");
                return;
            }
            JProxyInputSourceFileExcludedListener excludedListener = new JProxyInputSourceFileExcludedListener()
            {
                @Override
                public boolean isExcluded(File file, File rootFolderOfSources)
                {
                    String absPath = file.getAbsolutePath();
                    if (file.isDirectory())
                    {
                        return absPath.endsWith(File.separatorChar + "relproxy_builtin_ex");
                    }
                    else
                    {
                        return absPath.endsWith(File.separatorChar + Main.class.getSimpleName() + ".java");
                    }
                }
            };
            String classFolder = null; // Optional
            Iterable<String> compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"});
            long scanPeriod = 1000;
            RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() {
                @Override
                public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) {
                    System.out.println("Reloaded " + objNew + " Calling method: " + method);
                }
            };
            JProxyCompilerListener compilerListener = new JProxyCompilerListener(){
                @Override
                public void beforeCompile(File file)
                {
                    System.out.println("Before compile: " + file);
                }
                @Override
                public void afterCompile(File file)
                {
                    System.out.println("After compile: " + file);
                }
            };
            JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener()
            {
                @Override
                public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics)
                {
                    List<Diagnostic<  extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
                    int i = 1;
                    for (Diagnostic diagnostic : diagList)
                    {
                       System.err.println("Diagnostic " + i);
                       System.err.println("  code: " + diagnostic.getCode());
                       System.err.println("  kind: " + diagnostic.getKind());
                       System.err.println("  line number: " + diagnostic.getLineNumber());
                       System.err.println("  column number: " + diagnostic.getColumnNumber());
                       System.err.println("  start position: " + diagnostic.getStartPosition());
                       System.err.println("  position: " + diagnostic.getPosition());
                       System.err.println("  end position: " + diagnostic.getEndPosition());
                       System.err.println("  source: " + diagnostic.getSource());
                       System.err.println("  message: " + diagnostic.getMessage(null));
                       i++;
                    }
                }
            };
            RelProxyBuiltin rpbRoot = RelProxyBuiltinRoot.get();
            JProxyScriptEngine engine = rpbRoot.getJProxyScriptEngine();
            JProxyConfig jpConfig = JProxy.createJProxyConfig();
            jpConfig.setEnabled(true)
                    .setRelProxyOnReloadListener(proxyListener)
                    .setInputPath(inputPath)
                    .setJProxyInputSourceFileExcludedListener(excludedListener)
                    .setScanPeriod(scanPeriod)
                    .setClassFolder(classFolder)
                    .setCompilationOptions(compilationOptions)
                    .setJProxyCompilerListener(compilerListener)
                    .setJProxyDiagnosticsListener(diagnosticsListener);
            engine.init(jpConfig);
            System.out.println("RelProxy running");
        }
        public void tearDown()
        {
            RelProxyBuiltin rpbRoot = RelProxyBuiltinRoot.get();
            JProxyScriptEngine engine = rpbRoot.getJProxyScriptEngine();
            engine.stop();
            System.out.println("RelProxy stopped");
        }
        public void mainTest()
        {
            RelProxyBuiltin rpbRoot = RelProxyBuiltinRoot.get();
            TestListener listener = new TestListener();
            rpbRoot.addOutputListener(listener);
            assertTrue(rpbRoot.getOutputListenerCount() == 1);
            rpbRoot.removeOutputListener(listener);
            assertTrue(rpbRoot.getOutputListenerCount() == 0);
            rpbRoot.addOutputListener(listener);
            CommandListener commandListener = listener.getCommandListener();
            rpbRoot.addCommandListener(commandListener);
            assertTrue(rpbRoot.getCommandListenerCount() == 1);
            rpbRoot.removeCommandListener(commandListener);
            assertTrue(rpbRoot.getCommandListenerCount() == 0);
            rpbRoot.addCommandListener(commandListener);
            rpbRoot.runLoop(System.in,System.out);
        }
        private static void assertTrue(boolean res)
        {
            if (!res) throw new RuntimeException("Unexpected Error");
        }
    }

    看一下这段代码:

    Main.java (部分)

     URL res = this.getClass().getResource("/"); // .../target/classes/
            // Use example of RelProxy in development time:
            String inputPath = res.getFile() + "/../../src/main/java/";
            if (new File(inputPath).exists())
            {
                System.out.println("RelProxy to be enabled, development mode detected");
            }
            else
            {
                System.out.println("RelProxy disabled, production mode detected");
                return;
            }
            JProxyInputSourceFileExcludedListener excludedListener = new JProxyInputSourceFileExcludedListener()
            {
                @Override
                public boolean isExcluded(File file, File rootFolderOfSources)
                {
                    String absPath = file.getAbsolutePath();
                    if (file.isDirectory())
                    {
                        return absPath.endsWith(File.separatorChar + "relproxy_builtin_ex");
                    }
                    else
                    {
                        return absPath.endsWith(File.separatorChar + Main.class.getSimpleName() + ".java");
                    }
                }
            };

    我们获取并注册应用源代码的根目录,该代码“可能”会被重新加载。

    我们需要排除框架代码,因为这显然不是用户的代码(不需要重新加载)。此外,还需要排除 Main.java 文件,该文件包含了测试代码,也不需要重新加载,只有 TestListener.java 类(与 Main.java 在同一文件夹下)需要(必需)重新加载。

    最后 TestListener.java 类包含两个监听器,CommandListener 的实现采用匿名内部类的方式,主要目的是为了演示。

    TestListener.java

    package com.innowhere.relproxy_builtin_ex_main;
    import com.innowhere.relproxy_builtin_ex.CommandListener;
    import com.innowhere.relproxy_builtin_ex.OutputListener;
    import java.io.PrintStream;
    public class TestListener implements OutputListener
    {
        @Override
        public void write(PrintStream out)
        {
            out.println("uppercase");
            out.println("lowercase");
        }
        public CommandListener getCommandListener()
        {
            return new CommandListener()
            {
                @Override
                public void execute(String command,String text,PrintStream out)
                {
                    if ("uppercase".equals(command))
                        out.println(text.toUpperCase());
                    else if ("lowercase".equals(command))
                        out.println(text.toLowerCase());
                    else
                        out.println("Unknown command:" + command);
                }
            };
        }
    }

    先预定义可选项,然后执行 Main 类。为了校验 RelProxy 是否起作用,可以在不停止程序的运行的基础上增加一个新的可选项“same”。

    @Override
        public void write(PrintStream out)
        {
            out.println("uppercase");
            out.println("lowercase");
            out.println("same");  // NEW
        }
        public CommandListener getCommandListener()
        {
            return new CommandListener()
            {
                @Override
                public void execute(String command,String text,PrintStream out)
                {
                    if ("uppercase".equals(command))
                        out.println(text.toUpperCase());
                    else if ("lowercase".equals(command))
                        out.println(text.toLowerCase());
                    else if ("same".equals(command)) // NEW
                        out.println(text); // NEW
                    else
                        out.println("Unknown command:" + command);
                }
            };
        }
    }

    下一篇文章中将处理包含当前“same”的行为,不需要停止控制台应用。

    ItsNat web 框架可能是第一个使用 RelProxy 技术的应用(版本 v1.4)。

    注意:使用 RelProxy 0.8.7 或更高的版本,这个版本在嵌入方式上做了改进。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。