java动态类加载

最近做项目,有个需求需要实现动态类加载,通过尝试成功解决了该问题,记录下来,以便未来碰到此类问题有一个参考. 
package com.demo;

public class Person {

	protected String name;

	protected String job;

	public Person(String name, String job) {
		super();
		this.name = name;
		this.job = job;
	}

	public void introduction() {
		System.out.println("my name is " + name + ",job is " + job);
	}
}


package com.demo;
import com.demo.Person;

public class Teacher extends Person {

	public Teacher(String name, String job) {
		super(name, job);
	}

}


package com.demo;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public class Runner {

	public static final String JAVA_SUFFIX = ".java";
	public static final String CLASS_SUFFIX = ".class";

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void main(String[] args) throws Exception {
		String path = "d:/test/";
		String compileDir = "d:/test/classes/";
		String javaName = "Person";
		compileAlone(path, compileDir, javaName);
		String clazzName = "com.demo.Person";
		Class clazz = loadClas(compileDir, clazzName);

		System.out.println("load class name: " + clazz.getName());
		// 调用构造器创建对象
		Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class);
		Object person = declaredConstructor.newInstance("张三", "医生");
		// 调用类方法
		Method method = clazz.getDeclaredMethod("introduction");
		method.invoke(person);
		System.out.println("======================");
		javaName = "Teacher";
		// 有依赖时需要指定classpath
		compile(path, compileDir, javaName);
		clazz = loadClas(compileDir, clazzName);
		// 调用构造器创建对象
		declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class);
		person = declaredConstructor.newInstance("王五", "教师");
		// 调用类方法
		method = clazz.getDeclaredMethod("introduction");
		method.invoke(person);
	}

	/**
	 * @desc 不指定classpath
	 * @desc 适合场景:外部类文件没有其他类依赖
	 * 
	 * @param path
	 * @param compileDir
	 * @param javaName
	 */
	public static void compileAlone(String path, String compileDir, String javaName) {
		File f = new File(compileDir);
		if (!f.exists()) {
			f.mkdirs();
		}
		// 获取编译工具类 当前环境的编译器 javac
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		List<String> options = new ArrayList<String>();
		// -d 不指定默认与类文件同级
		options.add("-d");
		options.add(compileDir);
		String javaPath = Paths.get(path, javaName + JAVA_SUFFIX).toFile().getPath();
		options.add(javaPath);
		int compilerResult = compiler.run(null, null, null, options.toArray(new String[options.size()]));
		System.out.println(compilerResult == 0 ? "compile success" : "compile fail");
	}

	/**
	 * @desc 指定classpath
	 * @desc 适合场景:外部文件存在依赖
	 * @param path
	 * @param compileDir
	 * @param javaName
	 */
	public static void compile(String path, String compileDir, String javaName) {
		// 获取编译工具类 当前环境的编译器 javac
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		//
		List<String> options = new ArrayList<String>();
		options.add("-d");
		options.add(compileDir);
		options.add("-cp");
		options.add(compileDir);
		String javaPath = Paths.get(path, javaName + JAVA_SUFFIX).toFile().getPath();
		options.add(javaPath);
		int compilerResult = compiler.run(null, null, null, options.toArray(new String[options.size()]));
		System.out.println(compilerResult == 0 ? "compile success" : "compile fail");
	}

	@SuppressWarnings({ "resource", "rawtypes" })
	public static Class loadClas(String compileDir, String clazzName) throws Exception {
		URL[] urls = new URL[] { new URL("file:" + compileDir) };
		URLClassLoader loader = new URLClassLoader(urls);
		Class clazz = loader.loadClass(clazzName);
		System.out.println("load class success");
		return clazz;
	}

	/**
	 * @desc 当依赖类在当前项目时,采用如下加载方式
	 * 
	 * @param compileDir
	 * @param clazzName
	 * @return
	 * @throws Exception
	 */
	public static Class loadClass3(String compileDir, String clazzName) throws Exception {
		ClassLoader classLoader = Person.class.getClassLoader();
		URL[] urls = new URL[] { new URL("file:" + compileDir) };
		URLClassLoader loader = new URLClassLoader(urls, classLoader);
		Class<?> clazz = loader.loadClass(clazzName);
		return clazz;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值