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 block
e.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 block
e.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 block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.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,大家可以扩展,比如项目中有两个架包版本,结构全部都一样,但是两个架包都必须运行。这时自定义类加载器就有用了。

转:http://a123159521.iteye.com/blog/1095264

(转)自定义ClassLoader ----可以加载第三方jar包的更多相关文章

  1. 27 Java动态加载第三方jar包中的类

    我加载的方法是://参数fileName是jar包的路径,processorName 是业务类的包名+类名public static A load(String fileName, String pr ...

  2. maven加载第三方jar包

    <dependency> <groupId>com.yeepay</groupId> <artifactId>yop-sdk</artifactI ...

  3. 自定义ClassLoader,用于加载用户JAR包

    最近在考虑C/S结构程序的软件自动升级的实现方式,比如QQ.飞信等都自动升级的功能. 自动升级模块虽然还没有编码完成,但是思路还是比较清晰的. 自动升级过程中,升级文件的JAR包是专门加载到程序中去的 ...

  4. 加载所有jar包下指定文件

    加载所有jar包下指定文件: 如spring中加载 META-INF/spring.handlers 加载 org.springframework.core.io.support.Properties ...

  5. Spark on Yarn运行时加载的jar包

    spark on yarn运行时会加载的jar包有如下: spark-submit中指定的--jars $SPARK_HOME/jars下的jar包 yarn提供的jar包 spark-submit通 ...

  6. Classpath in jar关于java加载第三方jar的集中方法和详细解释。

    转载地址:http://www.iteye.com/topic/332580 大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个ja ...

  7. maven加载本地jar包到repository

    maven加载本地jar到repository 这是一个常见场景,此处以本地opencv jar文件导入repository为例 1.Ubuntu下 mvn install:install-file ...

  8. maven 手动加载第三方jar、zip包

    使用maven搭建工程时,难免要加载大量的第三方的jar包.zip包比较少用,而maven的官网提供的jar往往不能满足需求,这时需要我们手动加载到我们本地或nexus私服的仓库中. 1.加载jar包 ...

  9. maven加载第三方jar不能加载

    这个问题处于项目组,总算是解决了.下面是一些自己的做法. 1.说明介绍 公司现在用的是spring+maven,使用的公共maven库没有问题,但是想要把一些老的项目改造这种框架会出现一些问题. 因为 ...

随机推荐

  1. java 面试2019

    [第一部分] 面试要领[第1题] 流程必知必会[第2题] JDK源码[第二部分] 类和对象[第二篇] 面向对象基础[第1题] 面向对象是什么?[第2题] 类加载的过程[第3题] 类加载器有哪些[第4题 ...

  2. ubuntu 16.04 pecl 不能安裝 mcrypt

    vagrant@ubuntu-xenial:/etc/apt$ sudo pecl install mcrypt-1.0.1 downloading mcrypt-1.0.1.tgz ... Star ...

  3. Centos Apache 80 代理Tomcat 8080端口

    运行环境:Centos 6.5 Apache: 2.2.5 开启apache proxy的相应模块 编辑 /etc/httpd/conf/httpd.conf文件 sudo vim /etc/http ...

  4. CF 398 E(动态规划)

    传送门: http://codeforces.com/problemset/problem/398/E 题解: 首先答案不超过2. 最长环=1时,ans=0 最长环=2时,ans=1 否则,ans=2 ...

  5. (转)简述负载均衡&CDN技术

    转:http://www.cnblogs.com/mokafamily/p/4402366.html#commentform 曾经见到知乎上有人问“为什么像facebook这类的网站需要上千个工程师维 ...

  6. python round, ceil, flooor

    round(num, n) 保留n位小数 round(80.23456, 2) : 80.23 round(100.000056, 3) : 100.0 round(-100.000056, 3) : ...

  7. faster-rcnn算法总结

    faster-rcnn的整体流程比较复杂,尤其是数据的预处理部分,流程比较繁琐.我写faster-rcnn系列文章的目的是对该算法的原始版本有个整体的把握,如果需要使用该算法做一些具体的任务,推荐使用 ...

  8. 搞懂这7个Maven问题,带你吊打面试官!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 作者:张丰哲 www.jianshu.com/p/20b39ab6a88c 在如今的互联网项目开发当中,特别是Java领域, ...

  9. 4.1_springboot2.2任务之异步、定时、邮件任务

    1.异步任务 ​ 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spri ...

  10. 9-MySQL高级-主从同步时Slave_IO_Running:Connecting ; Slave_SQL_Running:Yes的情况故障排除

    推荐!! 各种情况都考虑在内,条理清楚!! https://blog.csdn.net/mbytes/article/details/86711508