博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义类加载器与spring的集成
阅读量:4185 次
发布时间:2019-05-26

本文共 2767 字,大约阅读时间需要 9 分钟。

转 

自定义ClassLoader相信很多人都用过,网上文章也有很多。但如何使用自定义的ClassLoader有时确实比较头痛。

如果启动入口自己可以控制还好说,大不了通过自定义ClassLoader加载所有类就可以了,但如果控制不了,比如说是通过TOMCAT或脚本来启动的,但又要用自定义的ClassLoader来加载外部类,那就郁闷了。

我碰到的情形就是如此,其中的ClassLoaderC是tomcat的类加载器,而classLoaderD是自定义的类加载器。通常来说,我们只能选择访问C或D其中一个下面的类。有没办法能同时访问它们下两个的类呢?

其中一种办法是Thread.currentThread().setContextClassLoader。相对比较方便,但这在多线程环境下很容易产生问题。

还有一种办法是通过反射调用,修改ClassLoaderC的parent为ClassLoaderD。我们知道ClassLoader的委托机制是先让parent(父)类加载器寻找,只有在parent找不到的时候才从自己的类路径中去寻找。这样我们通过修改parent就能达到同时访问的目的。当然,由于parent是私有的,而且没有提供写方法,所以还需要用反射来设置。

之前还尝试了另一种方法,即ClassLoader.addClass,但发现类是进去了,但package里没有,还是会加载不到类。

这种方法目前还在试用,大家觉得有什么问题欢迎提出来:)

public class ContainerClassLoader extends ClassLoader {        private Map
> loadedClasses = new HashMap
>(); private static ContainerClassLoader INSTANCE; private ContainerClassLoader() { super(ContainerClassLoader.class.getClassLoader().getParent()); } /** * 初始化 */ public static void init() { INSTANCE = new ContainerClassLoader(); try { INSTANCE.addThisToParentClassLoader(ContainerClassLoader.class .getClassLoader()); } catch (Exception e) { System.err.println("设置classloader到容器中时出现错误!"); } } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if (loadedClasses.containsKey(name)) { return loadedClasses.get(name); } return super.loadClass(name, resolve); } /** * 将this替换为指定classLoader的parent ClassLoader * * @param classLoader */ private void addThisToParentClassLoader(ClassLoader classLoader) throws Exception { Field field = ClassLoader.class.getDeclaredField("parent"); field.setAccessible(true); field.set(classLoader, this); } }

另外,在过程中还碰到spring加载时,classloader还没修改的问题。后来通过在web.xml中增加listener-class来实现。

后面还碰到了问题,如果将TOMCAT的当前ClassLoader的parent修改了,还是会碰到类无法识别的问题。 

原因是WebappClassLoader类也有个私有属性,与基类ClassLoader名称一样,而且是在WebappClassLoader类构造时赋值。 
处理方法:通过反射将WebappClassLoader对象的两个私有属性都修改。 如下: 

private void addThisToParentClassLoader(ClassLoader classLoader) throws Exception {         Field field;         try {             //将当前ClassLoader的parent属性修改为本对象(适用于WebClassLoader)             field = classLoader.getClass().getDeclaredField("parent");             field.setAccessible(true);             field.set(classLoader, this);         } catch (Exception e) {         }         //将当前ClassLoader的parent ClassLoader修改为本对象         field = ClassLoader.class.getDeclaredField("parent");         field.setAccessible(true);         field.set(classLoader, this);  }

 

转载地址:http://sndoi.baihongyu.com/

你可能感兴趣的文章
史上最难程序员的面试题!谷歌、百度、微软、阿里必答题
查看>>
为什么会出现“程序员千万不要学算法”这种言论?
查看>>
程序员如何做到快速升职?这几点你都做到了吗?
查看>>
第五届世界互联网大会重点介绍工业互联网
查看>>
凭什么程序员工资那么高?网友:某些文职坐着白领钱才让我惊奇
查看>>
程序员准时下班碰见领导,次月发工资时看到绩效莫名被扣20%
查看>>
程序员的月薪决定了对老板的态度:月薪50万,我与公司共存亡
查看>>
你见过最牛逼的程序员是什么样的?拳打回车键,脚踩Emacs编辑器
查看>>
相比加班的程序员,企业更喜欢“偷懒”的程序员?程序员偷的不是懒,是高效!
查看>>
初学Java必备基础知识,编程领域你需要掌握的关键点!
查看>>
阿里五年Java程序员的总结,献给还在迷茫中的你!
查看>>
程序员身上有异味,同事为什么都不会直接告诉他?
查看>>
大数据折射算法“歧视”?王思聪微博抽奖113位,仅有一位男性
查看>>
Java、C、C+ +、PHP、Python分别用来开发什么?一篇文章告诉你!
查看>>
Linux-ACL权限介绍
查看>>
Linux -文件系统
查看>>
Linux常用命令-进程管理
查看>>
Linux - 定时任务
查看>>
Linux - SHELL基础
查看>>
Linux-SHELL基础语法
查看>>