当前位置: 首页 > news >正文

在线设计图片网站总结做网页公司有哪些

在线设计图片网站总结,做网页公司有哪些,免费传奇无充值,大连德泰建设动态编译 Java 源码为 Class一.背景1.Jdk 版本2.需求二.Java 源码动态编译实现1.Maven 依赖2.源码包装类3.Java 文件对象封装类4.文件管理器封装类5.类加载器6.类编译器三.动态编译测试1.普通测试类2.接口实现类3.测试四.用动态编译 Class 替换 SpringBoot 的 Bean(…

动态编译 Java 源码为 Class

  • 一.背景
    • 1.Jdk 版本
    • 2.需求
  • 二.Java 源码动态编译实现
    • 1.Maven 依赖
    • 2.源码包装类
    • 3.Java 文件对象封装类
    • 4.文件管理器封装类
    • 5.类加载器
    • 6.类编译器
  • 三.动态编译测试
    • 1.普通测试类
    • 2.接口实现类
    • 3.测试
  • 四.用动态编译 Class 替换 SpringBoot 的 Bean(未完)

一.背景

1.Jdk 版本

版本查看命令:java -version

在这里插入图片描述

2.需求

本来想看下项目热部署的实现,比如 SpringBoot 不停机热加载 Jar 实现功能修改;后来看到 Jdk 支持源码动态编译,如果可以实现,那么就可以在线直接修改代码,再利用 SpringBoot 管理起来,替换旧的 Bean,实现功能修改。可能实际应用场景不多,可以做应急修改,线上服务最终还是需要把修改后的代码重新部署更为稳妥。

其实动态修改代码还可以通过 Arthas 实现,包括反编译、编译等更多功能

二.Java 源码动态编译实现

源码编译需要用到的关键类:

说明
JavaCompiler编译器 ToolProvider.getSystemJavaCompiler();
SimpleJavaFileObject文件对象类,可以表示源码、类文件
ClassLoader顶层类加载器,抽象类
ForwardingJavaFileManager文件管理器

项目结构如图

在这里插入图片描述

1.Maven 依赖

暂时只是一个 Maven 项目,未引入其他依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>DynamicDemo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>19</maven.compiler.source><maven.compiler.target>19</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>

2.源码包装类

基于 SimpleJavaFileObject 扩展,用于封装类名、源码信息

package org.example.demo.util;import javax.tools.SimpleJavaFileObject;
import java.io.IOException;
import java.net.URI;/*** @author moon* @date 2023-02-15 20:32* @since 1.8*/
public class CustomSourceCode extends SimpleJavaFileObject {/*** 类名称*/private String className;/*** 类源码*/private String contents;/*** 源码初始化* @param className* @param contents*/public CustomSourceCode(String className, String contents) {super(URI.create("string:///" + className.replace('.', '/')+ Kind.SOURCE.extension), Kind.SOURCE);this.contents = contents;this.className = className;}/*** 获取类名* @return*/public String getClassName() {return className;}/*** 源码字符序列* @param ignoreEncodingErrors ignore encoding errors if true* @return* @throws IOException*/public CharSequence getCharContent(boolean ignoreEncodingErrors)throws IOException {return contents;}
}

3.Java 文件对象封装类

基于 SimpleJavaFileObject 实现,封装了类名、类字节输出流信息

package org.example.demo.util;import javax.tools.SimpleJavaFileObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;/*** @author moon* @date 2023-02-15 20:52* @since 1.8*/
public class CustomJavaFileObject extends SimpleJavaFileObject {/*** 类名称*/private String className;/*** 输出的字节码流*/private ByteArrayOutputStream toByteArray = new ByteArrayOutputStream();/*** Construct a SimpleJavaFileObject of the given kind and with the* given URI.** @param className*/public CustomJavaFileObject(String className) throws URISyntaxException {super(new URI(className), Kind.CLASS);this.className = className;}@Overridepublic OutputStream openOutputStream() throws IOException {return toByteArray;}/*** 获取类名* @return*/public String getClassName() {return className;}/*** 获取字节信息* @return*/public byte[] getByteCode() {return toByteArray.toByteArray();}
}

4.文件管理器封装类

package org.example.demo.util;import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;/*** @author moon* @date 2023-02-15 20:00* @since 1.8*/
public class CustomJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> {/*** 自定义类加载器*/private CustomClassLoader loader;/*** 初始化* @param fileManager* @param loader*/protected CustomJavaFileManager(JavaFileManager fileManager, CustomClassLoader loader) {super(fileManager);this.loader = loader;}@Overridepublic JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className,JavaFileObject.Kind kind, FileObject sibling) {try {CustomJavaFileObject innerClass = new CustomJavaFileObject(className);loader.addJavaCode(innerClass);return innerClass;} catch (Exception e) {throw new RuntimeException("exception when creating in-memory output stream for  " + className, e);}}@Overridepublic ClassLoader getClassLoader(JavaFileManager.Location location) {return loader;}}

5.类加载器

用于从 CustomJavaFileObject 获取字节流,并通过 ClassLoader.defineClass 生成类

package org.example.demo.util;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author moon* @date 2023-02-15 20:50* @since 1.8*/
public class CustomClassLoader extends ClassLoader{/*** 缓存源代码对象*/private Map<String, CustomJavaFileObject> fileCacheMap = new ConcurrentHashMap<>(16);/*** 初始化类加载器* @param parent*/public CustomClassLoader(ClassLoader parent) {super(parent);}/*** 添加源码缓存* @param obj*/public void addJavaCode(CustomJavaFileObject obj) {fileCacheMap.put(obj.getName(), obj);}/*** 获取类* @param className*          The <a href="#binary-name">binary name</a> of the class** @return* @throws ClassNotFoundException*/@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {if (fileCacheMap.containsKey(className)){byte[] byteCode = fileCacheMap.get(className).getByteCode();return defineClass(className, byteCode, 0, byteCode.length);} else {return super.findClass(className);}}
}

6.类编译器

简要说明一下调用流程:读取源码 -> 编译 -> 加载为 Class => 构建对象及使用

package org.example.demo.util;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author moon* @date 2023-02-15 20:50* @since 1.8*/
public class CustomClassLoader extends ClassLoader{/*** 缓存源代码对象*/private Map<String, CustomJavaFileObject> fileCacheMap = new ConcurrentHashMap<>(16);/*** 初始化类加载器* @param parent*/public CustomClassLoader(ClassLoader parent) {super(parent);}/*** 添加源码缓存* @param obj*/public void addJavaCode(CustomJavaFileObject obj) {fileCacheMap.put(obj.getName(), obj);}/*** 获取类* @param className*          The <a href="#binary-name">binary name</a> of the class** @return* @throws ClassNotFoundException*/@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {if (fileCacheMap.containsKey(className)){byte[] byteCode = fileCacheMap.get(className).getByteCode();return defineClass(className, byteCode, 0, byteCode.length);} else {return super.findClass(className);}}
}

三.动态编译测试

1.普通测试类

定义一个普通测试类,包含:有、无参构造初始化,有、无参方法调用

用户积分器

package org.example.demo.common;public class UserSort {private String name;private int score;public UserSort (){}public UserSort (String name, int sort){this.name = name;this.score = sort;}public void reset(){this.score = 0;System.out.println("姓名: " + this.name + " 积分重置: " + this.score);}public void insert(int score){this.score += score;System.out.println("姓名: " + this.name + " 加分结果: " + this.score);}public void reduce(int score){this.score -= score;System.out.println("姓名: " + this.name + " 减分结果: " + this.score);}
}

封装一个静态方法:

public static void commonClass(CustomClassCompiler compiler) throws Exception{String sourceCode = "package org.example.demo.common;\n" +"\n" +"public class UserSort {\n" +"\n" +"    private String name;\n" +"    private int score;\n" +"\n" +"    public UserSort (){\n" +"    }\n" +"\n" +"    public UserSort (String name, int sort){\n" +"        this.name = name;\n" +"        this.score = sort;\n" +"    }\n" +"\n" +"    public void reset(){\n" +"        this.score = 0;\n" +"        System.out.println(\"姓名: \" + this.name + \" 积分重置: \" + this.score);\n" +"    }\n" +"\n" +"    public void insert(int score){\n" +"        this.score += score;\n" +"        System.out.println(\"姓名: \" + this.name + \" 加分结果: \" + this.score);\n" +"    }\n" +"\n" +"    public void reduce(int score){\n" +"        this.score -= score;\n" +"        System.out.println(\"姓名: \" + this.name + \" 减分结果: \" + this.score);\n" +"    }\n" +"}";String className = "org.example.demo.common.UserSort";compiler.addSource(className, sourceCode);compiler.compile(className);Class<?> clazz = compiler.getClassByName(className);System.out.println("无参构造及重置分数-----------------------");Object object = clazz.getDeclaredConstructor().newInstance();Method method = clazz.getDeclaredMethod("reset");method.invoke(object);System.out.println("有参构造及重置分数-----------------------");object = clazz.getDeclaredConstructor(String.class,int.class).newInstance("张三",0);method.invoke(object);System.out.println("加分-----------------------------------");method = clazz.getDeclaredMethod("insert",int.class);method.invoke(object,10);System.out.println("减分-----------------------------------");method = clazz.getDeclaredMethod("reduce",int.class);method.invoke(object,2);}

2.接口实现类

定义一个处理器接口,用于处理数据

package org.example.demo.handler;/*** @author moon* @date 2023-02-15 20:55* @since 1.8*/
public interface BaseHandler {/*** 处理器* @param content*/void deal(String content);
}

封装一个静态方法,实现类不再单独贴出,简单加了个打印,输出【春江花月夜】

public static void interfaceClass(CustomClassCompiler compiler) throws Exception {String sourceCode = "package com.demo.handler;\n" +"import org.example.demo.handler.BaseHandler;\n" +"public class DynamicHandler implements BaseHandler {\n" +"    \n" +"    @Override\n" +"    public void deal(String content) {\n" +"        System.out.println(content);\n" +"    }\n" +"}";String className = "com.demo.handler.DynamicHandler";compiler.addSource(className, sourceCode);compiler.compile(className);BaseHandler handler = (BaseHandler) compiler.getClassByName(className).getDeclaredConstructor().newInstance();handler.deal("春江花月夜");}

3.测试

在 App 类内直接定义一个 main 方法,调用上面两个静态方法

package org.example.demo;import org.example.demo.handler.BaseHandler;
import org.example.demo.util.CustomClassCompiler;import java.lang.reflect.Method;/*** @author moon* @date 2023-02-15 20:42* @since 1.8*/
public class App {public static void main(String[] args) throws Exception {CustomClassCompiler compiler = CustomClassCompiler.newInstance(null);commonClass(compiler);System.out.println("\n--------------------------------------------------\n");interfaceClass(compiler);}//TODO 静态方法 commonClass//TODO 静态方法 interfaceClass}

调用效果如下:

在这里插入图片描述

四.用动态编译 Class 替换 SpringBoot 的 Bean(未完)

未完待续 . . .

http://www.yayakq.cn/news/574393/

相关文章:

  • 网站开发专业术语大全网页建设多少钱
  • h5混搭php建设网站抖音小程序开发教程
  • 建设购物网站做推广哪家网站好
  • 创建网站赚钱html网页模板资源
  • 建设一个跟京东一样的网站网站建设项目申报书
  • 个人网站备案可以做项目网站手机百度网盘网页版登录入口
  • 丽水专业网站建设哪家好天津做网站美工
  • 作品网站松滋网络推广
  • 兰州网站建设和维护工作wordpress读者墙
  • 网站设计标准尺寸网站一直百度上搜不到是怎么回事
  • 厦门网站制作案例郑州最新通告
  • 娄底建设局网站装修设计培训学校
  • 自助做网站西宁建站
  • seo网站结构优化的方法企业网站可以自己做吗
  • 在linux系统上用什么做网站有没有做衣服的网站
  • 大公司的网站是怎么建的中国室内装饰设计网
  • 误入网站退不了怎么做网络营销推广方案策划
  • 网站后台登陆网址是多少学销售去哪个学校好
  • 网站建设专题页面低价网站备案
  • 企业门户网站建设与发展趋势在线编辑软件
  • 中国建设教育协会是个什么网站万户做网站怎么样
  • 烟台建设用地规划查询网站深圳华强北赛格大楼晃动
  • 纳森网络做网站多少钱龙炎电商小程序
  • 想自己做网站做推广wordpress 文章添加附件
  • 下载做蛋糕网站龙江网站开发
  • 关于网站开发与设计论文装修公司品牌包装设计
  • 网站下做二级域名企业宣传册制作
  • 网站预约功能怎么做广告设计公司
  • 北京网站制作成都住房和城乡建设部网站
  • 如何选择做网站长沙微信网站制作