动态加载远程Jar的实现方式

原创
2016/04/16 19:25
阅读数 6.1K

    通常动态加载Jar文件,是手动调用UrlClassLoader去加载,然后调用loader的loadClass获取到Class的引用,之后调用反射newInstance创建一个对象实例。

    这种方式写出来的代码太繁琐,并且newInstance返回的对象需要强制类型转换,并且对于IDE来说都是也是不友好的,不利于代码的批量重构。

    所以这种手动加载加载Jar的方式直接放弃了。

    最终的解决方案是动态设置JVM的classPath,并把classPath指定到远程的Jar包。

    1.我们把UserService封装到一个Jar,然后把Jar放到Http服务器的目录。

package com.sun.bean;

public class User {
	
	private String id;
	
	public User(String id) {
		this.id = id;
	}
	
	public void sayHello() {
		System.out.println("Hello everyone, my name is "+id);
	}
	
}
package com.sun.service;

import com.sun.bean.User;

public final class UserService {

	public static User getUserById(String id) {
		return new User(id);
	}
}
    然后编译打包成UserService.jar,并放到本地Web服务器的根目录。

    2.下面我们编写使用案例,留意setClassPath方法

package com.sun.bootstrap;

import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;

import com.sun.bean.User;
import com.sun.service.UserService;

public class Bootstrap {

	public final static void setClassPath(String path) {
		try {
			URI uri = new URI(path);
			URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
			Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
			add.setAccessible(true);
			add.invoke(classLoader, uri.toURL());
		} catch (Exception exp) {
			exp.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Bootstrap.setClassPath("http://localhost/UserService.jar");
		User jim = UserService.getUserById("JimGreen");
		jim.sayHello();
	}

}

    从Bootstrap.java的代码中可以发现,我们直接使用new UserService,而不是通过ClassLoader.loadClass().newInstance()的方式去创建UserService对象实例。

    3.编译Bootstrap类,这一步是关键,在编译时一定要指定classPath,否则编译不通过

javac -classpath /Users/M/workspace/lua/UserService.jar   com/sun/bootstrap/Bootstrap.java

    最后在com/sun/bootstrap路径下生成了Bootstrap.class文件。

    4.执行Bootstrap类   

java com/sun/bootstrap/Bootstrap
    结果打印:

Hello everyone, my name is JimGreen
    总结上述的方式, 我们可以按照平常的方式写代码(区别于loadClass的方式获取Class,然后newInstance),关键点在于调用了SystemClassLoader.addURL添加类加载路径,这样JVM可以主动帮我们 动态加载远程jar包。
展开阅读全文
打赏
2
14 收藏
分享
加载中

引用来自“cwj_osc”的评论


import com.sun.service.UserService;

这个包是怎么来的 动态加载之前应该没有这个包啊,已经有了还加载干嘛。
熟悉maven依赖管理的话,这个就比较好理解了,这个和maven中的provided scope属性相似的,这个类是打包在另外一个jar中,并没有和使用者类放在同一个jar包,他俩分别被打包到一个jar中,就是说运行时导入该类,至于运行时导入,jvm可以通过classpath帮我们默默导入,另外我们可以自己通过动态加载的方式主动把该类导入进来,文中只是通过网络加载了jar包,也可以通过本地路径的方式加载jar包,可以阅读下关于classloader方面的知识,希望对你有所帮助。😄
2017/07/12 20:42
回复
举报

import com.sun.service.UserService;

这个包是怎么来的 动态加载之前应该没有这个包啊,已经有了还加载干嘛。
2017/07/12 14:31
回复
举报

引用来自“霸争希夫时代”的评论

主要用来干什么
把依赖包放在一台Web服务器上面,通过调用SystemClassLoader.addURL,让150台Java服务器共享这台Web服务器上面的代码。
2016/04/17 02:16
回复
举报
主要用来干什么
2016/04/16 20:44
回复
举报
更多评论
打赏
4 评论
14 收藏
2
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部