Java核心技术之脚本和编译
来源:互联网 发布:健身理论 知乎 编辑:程序博客网 时间:2024/06/09 19:41
脚本
//创建一个脚本引擎管理器ScriptEngineManager manager = new ScriptEngineManager();//遍历引擎管理器所支持的所有脚本引擎for (ScriptEngineFactory factory : manager.getEngineFactories()) { System.out.println(factory.getEngineName());}//根据引擎名字获取一个脚本引擎对象final ScriptEngine engine = manager.getEngineByName("js");//构造一个JFrame对象,里面包含一个JPanel和三个JButton对象JFrame frame = (JFrame) Class.forName("buttons1.ButtonFrame").newInstance();//向引擎对象中添加绑定(Bean的名字和实例的映射),这样在脚本的执行上下文中就可以访问Java对象(上面的UI对象)private static void getComponentBindings(Component c, ScriptEngine engine) { String name = c.getName(); if (name != null) engine.put(name, c); if (c instanceof Container) { for (Component child : ((Container) c).getComponents()) getComponentBindings(child, engine); }}getComponentBindings(frame, engine);//加载配置文件js.properties/*yellowButton.action=panel.background = java.awt.Color.YELLOWblueButton.action=panel.background = java.awt.Color.BLUEredButton.action=panel.background = java.awt.Color.RED*/final Properties events = new Properties();InputStream in = frame.getClass().getResourceAsStream("js.properties");events.load(in);//根据配置文件设置三个按钮的点击监听器,监听器里面使用脚本引擎解析执行配置文件中相应JavaScript语句(第一个等号后面的内容)for (final Object e : events.keySet()) { String[] s = ((String) e).split("\\."); addListener(s[0], s[1], (String) events.get(e), engine);}private static void addListener(String beanName, String eventName, final String scriptCode, final ScriptEngine engine) throws ReflectiveOperationException, IntrospectionException { Object bean = engine.get(beanName); EventSetDescriptor descriptor = getEventSetDescriptor(bean, eventName); if (descriptor == null) return; //使用动态代理生成一个对象 descriptor.getAddListenerMethod().invoke(bean, Proxy.newProxyInstance(null, new Class[] { descriptor.getListenerType() }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //解析JavaScript脚本 engine.eval(scriptCode); return null; } } ));}private static EventSetDescriptor getEventSetDescriptor(Object bean, String eventName) throws IntrospectionException{ for (EventSetDescriptor descriptor : Introspector.getBeanInfo(bean.getClass()).getEventSetDescriptors()) if (descriptor.getName().equals(eventName)) return descriptor; return null;}
编译
动态生成类
//构造一个JavaFileObject对象,用于编译JavaFileObject source = buildSource("buttons2.ButtonFrame");//动态生成了一个继承于buttons2.ButtonFrame的类x.Frame(包括包名)static JavaFileObject buildSource(String superclassName) throws IOException, ClassNotFoundException { StringBuilderJavaSource source = new StringBuilderJavaSource("x.Frame"); source.append("package x;\n"); source.append("public class Frame extends " + superclassName + " {"); source.append("protected void addEventHandlers() {"); final Properties props = new Properties(); props.load(Class.forName(superclassName).getResourceAsStream("action.properties")); for (Map.Entry<Object, Object> e : props.entrySet()) { String beanName = (String) e.getKey(); String eventCode = (String) e.getValue(); source.append(beanName + ".addActionListener(new java.awt.event.ActionListener() {"); source.append("public void actionPerformed(java.awt.event.ActionEvent event) {"); source.append(eventCode); source.append("} } );"); } source.append("} }"); return source;}//StringBuilderJavaSource类扩展了SimpleJavaFileObject类,如下:public class StringBuilderJavaSource extends SimpleJavaFileObject { private StringBuilder code; public StringBuilderJavaSource(String name) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); code = new StringBuilder(); } public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } public void append(String str) { code.append(str); code.append('\n'); }}
编译类
//用于存放编译后的结果final List<ByteArrayJavaClass> classFileObjects = new ArrayList<>();//编译器诊断输出对象DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();//JavaFileManager对象,将结果放入classFileObjects数组JavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);fileManager = new ForwardingJavaFileManager<JavaFileManager>(fileManager) { public JavaFileObject getJavaFileForOutput(Location location, final String className, Kind kind, FileObject sibling) throws IOException { if (className.startsWith("x.")) { ByteArrayJavaClass fileObject = new ByteArrayJavaClass(className); classFileObjects.add(fileObject); return fileObject; } else return super.getJavaFileForOutput(location, className, kind, sibling); }};//ByteArrayJavaClass类如下public class ByteArrayJavaClass extends SimpleJavaFileObject { private ByteArrayOutputStream stream; public ByteArrayJavaClass(String name) { super(URI.create("bytes:///" + name), Kind.CLASS); stream = new ByteArrayOutputStream(); } public OutputStream openOutputStream() throws IOException { return stream; } public byte[] getBytes() { return stream.toByteArray(); }}//获取一个编译器对象JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();//创建一个编译任务并开始编译 JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, Arrays.asList(source));boolean result = task.call();
使用类
//使用编译后的类集合构造一个自定义的ClassLoader,然后加载类x.Frame,并构造一个Frame的对象。Map<String, byte[]> byteCodeMap = new HashMap<>();for (ByteArrayJavaClass cl : classFileObjects) byteCodeMap.put(cl.getName().substring(1), cl.getBytes());ClassLoader loader = new MapClassLoader(byteCodeMap);JFrame frame = (JFrame) loader.loadClass("x.Frame").newInstance();//最后自定义的MapClassLoader如下:public class MapClassLoader extends ClassLoader { private Map<String, byte[]> classes; public MapClassLoader(Map<String, byte[]> classes) { this.classes = classes; } protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] classBytes = classes.get(name); if (classBytes == null) throw new ClassNotFoundException(name); Class<?> cl = defineClass(name, classBytes, 0, classBytes.length); if (cl == null) throw new ClassNotFoundException(name); return cl; }}
0 0
- Java核心技术之脚本和编译
- Java核心技术之抽象类和接口
- java核心技术之-----整形和浮点类型
- Java核心技术之容器
- java核心技术之反射
- Java核心技术之反射
- JAVA高级【8.1】《Java核心技术2》脚本
- Java核心技术之Comparator和Comparable在排序中的应用
- java核心技术之IO流(二)FileInputStream和FileOutputStream
- java核心技术之IO流(三)FileReader和FileWriter
- java核心技术之IO流(四)BufferedInputStream和BufferedOutputStream
- java核心技术之IO流(五)BufferedReader和BufferedWriter
- java核心技术之IO流(六)DataInputStream和DataOutputStream
- Java核心技术之------char类型和boolean类型
- Java核心技术之Java 数据类型
- java编译脚本的进阶之路
- JAVA高级【8.2】《Java核心技术2》编译
- java核心技术 之基础知识(一)
- iOS RGB色值宏定义设置
- Liblinphone 3.9.1中文--Modules--Managing proxies
- 因特网传输层协议
- js中做一个button按钮,页面开始五秒钟之后才可进行点击,并且要求按钮上实时显示当前所剩秒数
- spring boot 学习--01--springboot开始
- Java核心技术之脚本和编译
- 用户界面框架jQuery EasyUI示例大全之链接按钮
- maven install jar file to local repository
- Java程序10个面向对象设计原则
- Redis主从复制
- 越南机场被黑事件主角:1937CN Team宣布停止所有活动并关闭网站
- Webform GridView列表增删改查结合EF数据绑定
- n_multiple vectors and linearly independent
- 黄金平衡