自定义ClassLoader
来源:互联网 发布:乐高幻影忍者玩具淘宝 编辑:程序博客网 时间:2024/06/05 05:26
来源:http://a123159521.iteye.com/blog/1095264
package com.classloader.util;import java.io.IOException;import java.net.MalformedURLException;import java.net.URL;import java.net.URLClassLoader;import java.net.URLStreamHandlerFactory;import java.security.CodeSource;import java.security.PermissionCollection;import java.util.Enumeration;import java.util.jar.Manifest;public class NetworkClassLoader extends URLClassLoader {String baseUrl;public String getBaseUrl() {return baseUrl;}public void setBaseUrl(String baseUrl) {this.baseUrl = baseUrl;}public NetworkClassLoader(){this(new URL[]{});}/** * URL 以'/'结尾的为目录 * 否则为jar包 * 未指定其父类加载器为系统类加载器 * @param urls */public NetworkClassLoader(URL[] urls) {super(urls);}/** * 同上,指定classLoader * @param urls * @param parent */public NetworkClassLoader(URL[] urls, ClassLoader parent) {super(urls,parent);}/** * 同上,URL工厂处理器 * @param urls * @param parent * @param factory */public NetworkClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { super(urls,parent,factory);}/** * [添加baseUrl] * @param url */public void addURL(String url){URL uurl=null;try {uurl = new URL(baseUrl+url);} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();}addURL(uurl);}/** * 添加url[添加baseUrl] */protected void addURL(URL url) {super.addURL(url);}/** * 返回urls */public URL[] getURLs() {return super.getURLs();}/** * 查找类对象 * 从以上的URLS中查找加载当前类对象[会打开所有的jars去查找指定的类] * (可以通过调用findClass来得到以上URL加载包中的类) */protected Class<?> findClass(String name) throws ClassNotFoundException {return super.findClass(name);}/** * defineClass SecureClassLoader定义为最终方法,不允许更改. * 在使用这个类对象前,必须先resolved(解析) *//** * 查找资源[自定义相对URL查找路径] * 从以上的URLS中查找当前名称的资源 * 这个必须重写,因为是public 哈哈 */public URL findResource(String name) {URL url = null;try {url = new URL(baseUrl+name);} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return url;}/** * 查找资源列表[URL查找路径] */public Enumeration<URL> findResources(String name) throws IOException {return super.findResources(name);}/** * 在当前的ClassLoader中,定义一个新的Package,Package的属性由Manifest指定.这个包的源文件 */protected Package definePackage(String name, Manifest man, URL url)throws IllegalArgumentException {return super.definePackage(name, man, url);}/** * 加载路径权限 */protected PermissionCollection getPermissions(CodeSource codesource) {return super.getPermissions(codesource);}}
以下是用法:
NetworkClassLoader loader = new NetworkClassLoader();loader.setBaseUrl("file:///F:\\框架\\maven\\app\\jms\\src\\main\\webapp\\modules\\");loader.addURL("App/lib/test.jar");loader.addURL("App/lib/test1.jar");loader.addURL("App/template/view.vm");loader.addURL("App/config.xml");
这里初始化了此类加载器所使用的类资源,配置文件等。
以下是如何加载类资源:
Class clazz= loader.findClass("com.jvm.look.A");//加载类以下是加载配置文件资源
URL uuu = loader.findResource("App/config.xml");有一点需要注意的,这个类加载器还是双亲委托机制,比如有一个类"com.annotation.table.Test"在父类加载器中如果已经加载过了,那么如果这个类在test.jar中存在,那么不会重新定义加载,而使用父类加载器加载的类,有人问了,那我如何覆盖父类加载器中定义的类。
可以进行如下操作:
Class clazz2= loader.findClass("com.annotation.table.Test");重新加载类,类的加载序列我在上一篇已经讲过了,不熟悉的可以看以上文章.
可能有人会问了,如果每一个类都这样,那我不崩溃了,我需要把我加载的jar覆盖父类加载器中定义的所有类.
/** * 覆盖父加载器中定义的类,使用当前类加载器加载资源,那么所有的类都在此加载器中执行. * 这样,所有URL中的类都通过此类加载器加载,也就是说URL中的类的定义类加载器就是当前类加载器. * 建议:尽量不要使用这种方式覆盖父加载器定义的类.[按一种约定双亲委托机制加载] * (如果重载了,那么尽量使用此loader加载类,这样所有逻辑都在此ClassLoader中运行,当然还有SDK还是从双亲加载) * 可以在SDK中定义接口,在此JAR里面提供实现. */public void initAllJar(){URL[] urls = this.getURLs();for(URL urll:urls){String url = urll.getFile();//重新定义这个架包中的所有类.if(url.endsWith("jar")){File jarFile = getJarFile(url);JarFile jarFileTemp = null;try {jarFileTemp = new JarFile(jarFile);Enumeration<JarEntry> en = jarFileTemp.entries();while (en.hasMoreElements()) {JarEntry je = en.nextElement();String name = je.getName();if (name.endsWith(CLASS_FILE)) {String className = name.substring(0, name.length()- CLASS_FILE.length());findClass(pathToDot(className));}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}/** * 转jar包路径和jar文件名为具体文件. * * @param root * @param jar * @return */private File getJarFile(String file) {if (file.startsWith(PREFIX_FILE))file = file.substring(PREFIX_FILE.length());int end = file.indexOf(JAR_URL_SEPERATOR);if (end != (-1))file = file.substring(0, end);return new File(file);} /** * 转路径为包名[/ ==> .]/[\\ ==> .] * @param s * @return */ private String pathToDot(String s) { return s.replace('/', '.').replace('\\', '.'); }
其实JDK中已经提供了好几个ClassLoader,大家可以扩展,比如项目中有两个架包版本,结构全部都一样,但是两个架包都必须运行。这时自定义类加载器就有用了。
0 0
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- 自定义ClassLoader
- Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)
- 自定义一个ClassLoader.
- 自定义EclipsePlugin ClassLoader (2)
- 自定义classloader的实现
- 自定义ClassLoader 简单例子
- java 自定义ClassLoader
- 自定义ClassLoader类
- 自定义 Java ClassLoader
- 自定义ClassLoader解析
- sgu 414 Orthogonal Circles 圆的正交
- HDU 2814 Interesting Fibonacci 循环节
- CentOs使用yum方式安装wine 并安装Source Insight
- poj3211 Washing Clothes
- 胜利大逃亡
- 自定义ClassLoader
- org.hibernate.exception.ConstraintViolationException: could not insert
- windows驱动数字签名
- 解决mysql自动断掉连接的问题
- 关系型数据库与NOSQL
- 钛备份 - Titanium Backup Pro v6.2.0-Test4 直装破解版
- POJ 2632 Crashing Robots
- [Leetcode] Binary Tree Zigzag Level Order Traversal
- CNN相关资料