1. package com.classloader.util;
  2.  
  3. import java.io.IOException;
  4. import java.net.MalformedURLException;
  5. import java.net.URL;
  6. import java.net.URLClassLoader;
  7. import java.net.URLStreamHandlerFactory;
  8. import java.security.CodeSource;
  9. import java.security.PermissionCollection;
  10. import java.util.Enumeration;
  11. import java.util.jar.Manifest;
  12.  
  13. public class NetworkClassLoader extends URLClassLoader {
  14.  
  15. String baseUrl;
  16.  
  17. public String getBaseUrl() {
  18. return baseUrl;
  19. }
  20.  
  21. public void setBaseUrl(String baseUrl) {
  22. this.baseUrl = baseUrl;
  23. }
  24.  
  25. public NetworkClassLoader(){
  26. this(new URL[]{});
  27. }
  28.  
  29. /**
  30. * URL 以'/'结尾的为目录
  31. * 否则为jar包
  32. * 未指定其父类加载器为系统类加载器
  33. * @param urls
  34. */
  35. public NetworkClassLoader(URL[] urls) {
  36. super(urls);
  37. }
  38.  
  39. /**
  40. * 同上,指定classLoader
  41. * @param urls
  42. * @param parent
  43. */
  44. public NetworkClassLoader(URL[] urls, ClassLoader parent) {
  45. super(urls,parent);
  46. }
  47.  
  48. /**
  49. * 同上,URL工厂处理器
  50. * @param urls
  51. * @param parent
  52. * @param factory
  53. */
  54. public NetworkClassLoader(URL[] urls, ClassLoader parent,
  55. URLStreamHandlerFactory factory) {
  56. super(urls,parent,factory);
  57. }
  58.  
  59. /**
  60. * [添加baseUrl]
  61. * @param url
  62. */
  63. public void addURL(String url){
  64. URL uurl=null;
  65. try {
  66. uurl = new URL(baseUrl+url);
  67. } catch (MalformedURLException e) {
  68. // TODO Auto-generated catch block
  69. e.printStackTrace();
  70. }
  71. addURL(uurl);
  72. }
  73.  
  74. /**
  75. * 添加url[添加baseUrl]
  76. */
  77. protected void addURL(URL url) {
  78. super.addURL(url);
  79. }
  80.  
  81. /**
  82. * 返回urls
  83. */
  84. public URL[] getURLs() {
  85. return super.getURLs();
  86. }
  87.  
  88. /**
  89. * 查找类对象
  90. * 从以上的URLS中查找加载当前类对象[会打开所有的jars去查找指定的类]
  91. * (可以通过调用findClass来得到以上URL加载包中的类)
  92. */
  93. protected Class<?> findClass(String name) throws ClassNotFoundException {
  94. return super.findClass(name);
  95. }
  96.  
  97. /**
  98. * defineClass SecureClassLoader定义为最终方法,不允许更改.
  99. * 在使用这个类对象前,必须先resolved(解析)
  100. */
  101.  
  102. /**
  103. * 查找资源[自定义相对URL查找路径]
  104. * 从以上的URLS中查找当前名称的资源
  105. * 这个必须重写,因为是public 哈哈
  106. */
  107. public URL findResource(String name) {
  108. URL url = null;
  109. try {
  110. url = new URL(baseUrl+name);
  111. } catch (MalformedURLException e) {
  112. // TODO Auto-generated catch block
  113. e.printStackTrace();
  114. }
  115. return url;
  116. }
  117.  
  118. /**
  119. * 查找资源列表[URL查找路径]
  120. */
  121. public Enumeration<URL> findResources(String name) throws IOException {
  122. return super.findResources(name);
  123. }
  124.  
  125. /**
  126. * 在当前的ClassLoader中,定义一个新的Package,Package的属性由Manifest指定.这个包的源文件
  127. */
  128. protected Package definePackage(String name, Manifest man, URL url)
  129. throws IllegalArgumentException {
  130. return super.definePackage(name, man, url);
  131. }
  132.  
  133. /**
  134. * 加载路径权限
  135. */
  136. protected PermissionCollection getPermissions(CodeSource codesource) {
  137. return super.getPermissions(codesource);
  138. }
  139. }

以下是用法:

  1. NetworkClassLoader loader = new NetworkClassLoader();
  2. loader.setBaseUrl("file:///F:\\框架\\maven\\app\\jms\\src\\main\\webapp\\modules\\");
  3.  
  4. loader.addURL("App/lib/test.jar");
  5. loader.addURL("App/lib/test1.jar");
  6. loader.addURL("App/template/view.vm");
  7. loader.addURL("App/config.xml");

这里初始化了此类加载器所使用的类资源,配置文件等。
以下是如何加载类资源:

  1. Class clazz= loader.findClass("com.jvm.look.A");//加载类

以下是加载配置文件资源

  1. URL uuu = loader.findResource("App/config.xml");

有一点需要注意的,这个类加载器还是双亲委托机制,比如有一个类"com.annotation.table.Test"在父类加载器中如果已经加载过了,那么如果这个类在test.jar中存在,那么不会重新定义加载,而使用父类加载器加载的类,有人问了,那我如何覆盖父类加载器中定义的类。
可以进行如下操作:

  1. Class clazz2= loader.findClass("com.annotation.table.Test");

重新加载类,类的加载序列我在上一篇已经讲过了,不熟悉的可以看以上文章.
可能有人会问了,如果每一个类都这样,那我不崩溃了,我需要把我加载的jar覆盖父类加载器中定义的所有类.

  1. /**
  2. * 覆盖父加载器中定义的类,使用当前类加载器加载资源,那么所有的类都在此加载器中执行.
  3. * 这样,所有URL中的类都通过此类加载器加载,也就是说URL中的类的定义类加载器就是当前类加载器.
  4. * 建议:尽量不要使用这种方式覆盖父加载器定义的类.[按一种约定双亲委托机制加载]
  5. * (如果重载了,那么尽量使用此loader加载类,这样所有逻辑都在此ClassLoader中运行,当然还有SDK还是从双亲加载)
  6. * 可以在SDK中定义接口,在此JAR里面提供实现.
  7. */
  8. public void initAllJar(){
  9. URL[] urls = this.getURLs();
  10.  
  11. for(URL urll:urls){
  12. String url = urll.getFile();
  13. //重新定义这个架包中的所有类.
  14. if(url.endsWith("jar")){
  15. File jarFile = getJarFile(url);
  16. JarFile jarFileTemp = null;
  17. try {
  18. jarFileTemp = new JarFile(jarFile);
  19. Enumeration<JarEntry> en = jarFileTemp.entries();
  20. while (en.hasMoreElements()) {
  21. JarEntry je = en.nextElement();
  22. String name = je.getName();
  23. if (name.endsWith(CLASS_FILE)) {
  24. String className = name.substring(0, name.length()
  25. - CLASS_FILE.length());
  26. findClass(pathToDot(className));
  27. }
  28. }
  29.  
  30. } catch (IOException e) {
  31. // TODO Auto-generated catch block
  32. e.printStackTrace();
  33. } catch (ClassNotFoundException e) {
  34. // TODO Auto-generated catch block
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  39. }
  40.  
  41. /**
  42. * 转jar包路径和jar文件名为具体文件.
  43. *
  44. * @param root
  45. * @param jar
  46. * @return
  47. */
  48. private File getJarFile(String file) {
  49. if (file.startsWith(PREFIX_FILE))
  50. file = file.substring(PREFIX_FILE.length());
  51. int end = file.indexOf(JAR_URL_SEPERATOR);
  52. if (end != (-1))
  53. file = file.substring(0, end);
  54. return new File(file);
  55. }
  56.  
  57. /**
  58. * 转路径为包名[/ ==> .]/[\\ ==> .]
  59. * @param s
  60. * @return
  61. */
  62. private String pathToDot(String s) {
  63. return s.replace('/', '.').replace('\\', '.');
  64. }

其实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. RHEL5/6/7中常用命令及命令之间的差异

    System basics Task RHEL5 RHEL6 RHEL7 View subscription information /etc/sysconfig/rhn/systemid /etc/ ...

  2. C# 简单的统计指定几个字符组合的所有结果

    比如 用 a,b,c,d 4个字符组成一个8个长度的字符串,问一共有多少可能,应该有4的8次方种,用代码简单实现 private string[] AAA() { string[] cs = { &q ...

  3. js实现正则判断手机号

    //判断是否为手机号的正则表达式 function phoneFun(phones){ var myreg = /^[1][3,4,5,7,8,9][0-9]{9}$/; if (!myreg.tes ...

  4. shell脚本明文密码隐藏且加密

    将密码放到文件中去,比如/root/.pass.txtpassword=`</root/.pass.txt`还怕密码泄露的话,就把pass.txt权限设置下. chattr +i /root/. ...

  5. 26.String类(1)

    1. 下面是一个使用equals的例子: 我查看了一下源代码,string类中equals方法的源代码如下: public boolean equals(Object anObject) { if ( ...

  6. python模块:typing

    很多人在写完代码一段时间后回过头看代码,很可能忘记了自己写的函数需要传什么参数,返回什么类型的结果,就不得不去阅读代码的具体内容,降低了阅读的速度,加上Python本身就是一门弱类型的语言,这种现象就 ...

  7. 零距离接触阿里云时序时空数据库TSDB

    概述 最近,Amazon新推出了完全托管的时间序列数据库Timestream,可见,各大厂商对未来时间序列数据库的重视与日俱增.阿里云TSDB是阿里巴巴集团数据库事业部研发的一款高性能分布式时序时空数 ...

  8. HDFS(Hadoop Distributed File System)的组件架构概述

    1.hadoop1.x和hadoop2.x区别 2.组件介绍 HDFS架构概述1)NameNode(nn): 存储文件的元数据,如文件名,文件目录结构,文件属性(生成时间,副本数,文件权限),以及每个 ...

  9. document.body / document.ducumentElement /等获取高度和宽度的区别

    document.body / document.ducumentElement /等获取高度和宽度的区别 <!DOCTYPE html> <html> <head la ...

  10. centos7.2搭建kubernetes1.5.2+dashboard

    一.    简介 近来容器对企业来说已经不是什么陌生的概念,Kubernetes作为Google开源的容器运行平台,受到了大家的热捧.搭建一套完整的kubernetes平台,也成为试用这套平台必须迈过 ...