微服务(三)---Common

目录

对于一些直接使用jdk底层的代码我是很难看懂的,逐渐去看看 源码,比瞎几把coding要重要很多

起因

1。字节码生成,在spring 动态代理AOP 中,spring框架会在运行期间动态创建一个被代理对象的子类,如果我们有这种需求,应该怎么办
即程序动态的生成Java源文件,由JDK进行编译,最后动态加载到JVM并运行。
2。jdk 中带有编译器相关的Api,所以我们可以直接编译我们动态生成的java源文件

3。我要将 src.java 的文件编译成 .class文件
javaCompiler类编译文件,并且使用 URlClassLoader类加载编译好的class 文件中的方法

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, "src.java"); 

4。为了直接从内存中直接加载java 的源文件,我们可以使用 ForwardingJavaFileManager,继承并重写URLClassLoader.findClass()就可以实现将编译结果直接以byte[]形式返回,

实际应用

//在内存中编译String类型的Java代码
public class JavaStringCompiler { 
    private JavaCompiler compiler; 
    private String javaClassPath = null; 
    private StandardJavaFileManager stdManager; 
    public JavaStringCompiler(String javaClassPath) { 
        // 需要辅助加入的jar文件路径
        this.javaClassPath = javaClassPath;
        this.compiler = ToolProvider.getSystemJavaCompiler();
        this.stdManager = compiler.getStandardFileManager(null, null, null);
    }

    /**
     * Compile a Java source file in memory.
     * 
     * @param fileName Java文件名, 例如:Test.java
     * @param source Java源码字符串
     * @return 编译结果Map<String, byte[]>
     * @throws IOException If compile error.
     */
    public Map<String, byte[]> compile(String fileName, String source) {  
        // Java编译选项
        Iterable<String> options = Arrays.asList("-encoding", "UTF-8", "-classpath", javaClassPath);

        // 打开当前的jar文件列表
        List<File> fileList = new ArrayList<File>();
        for (String str : javaClassPath.split(";")) {
            if (StringUtil.isNotBlank(str)) {
                try {
                    fileList.add(new File(str));
                } catch (Exception e) {}
            }
        }

        try (MemoryJavaFileManager manager = new MemoryJavaFileManager(stdManager)) {
            JavaFileObject javaFileObject = manager.makeStringSource(fileName, source);
            try {
                this.stdManager.setLocation(StandardLocation.CLASS_PATH, fileList);
            } catch (Exception e) {
                throw new UnexCommonException("StandardLocation.CLASS_PATH setting failed.", e);
            }
            CompilationTask task = compiler.getTask(null, manager, null, options, null, Arrays.asList(javaFileObject));

            Boolean result = task.call();
            if (result == null || !result.booleanValue()) {
                throw new UnexBaseException("Compilation failed.");
            }
            return manager.getClassBytes();
        } catch (Exception e) {
            throw new UnexBaseException("Compilation failed.");
        }
    }

    /**
     * 根据编辑的class信息加载相应的class对象
     * 
     * @param name 完整的Class名称
     * @param classBytes 编译的Class对应的Map对象
     * @return Class对象:Class<?>
     * @throws ClassNotFoundException
     * @throws IOException
     */
    public Class<?> loadClass(String name, Map<String, byte[]> classBytes) throws ClassNotFoundException,IOException {

        try ( MemoryClassLoader classLoader = new UnexMemoryClassLoader(classBytes)) {

            return classLoader.loadClass(name);
        }
    }
}

内存class 加载器

/**
 * 内存Class加载器 
 */
public class  MemoryClassLoader extends URLClassLoader { 
    // class name to class bytes:
    private static Map<String, byte[]> CLASS_BYTES_MAP = new HashMap<String, byte[]>();

    private static Map<String, Class<?>> DEFINED_CLASS_MAP = new HashMap<String, Class<?>>();

    public UnexMemoryClassLoader() {

        super(new URL[0], UnexMemoryClassLoader.class.getClassLoader());
    }

    public  MemoryClassLoader(Map<String, byte[]> classBytes) {

        this();

        for (String key : classBytes.keySet()) {
            if (!CLASS_BYTES_MAP.containsKey(key)) {

                logger.debug("UnexMemoryClassLoader():::" + key);
                CLASS_BYTES_MAP.put(key, classBytes.get(key));
            }
        }
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        Class<?> definedClass = DEFINED_CLASS_MAP.get(name);
        if (definedClass != null) {
            logger.debug("findClass() end:::DEFINED_CLASS_MAP found.");
            return definedClass;
        }

        byte[] buf = CLASS_BYTES_MAP.get(name);
        if (buf == null) {
            return this.getClass().getClassLoader().loadClass(name);
        }

        definedClass = defineClass(name, buf, 0, buf.length);

        DEFINED_CLASS_MAP.put(name, definedClass);

        logger.debug("findClass() end:::" + name);
        return definedClass;
    }

    /**
     * @param name
     * @see java.lang.ClassLoader#loadClass(java.lang.String)
     */
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException { 
        Class<?> loadedClass = loadClass(name, false); 
        logger.debug("loadClass() end:::loadedClass=" + loadedClass);
        return loadedClass;
    }

}

猜你喜欢

转载自blog.csdn.net/sinat_27639721/article/details/78782155
今日推荐