说起classloader可能最先想到的就是双亲委托。这次就换个角度来谈这个。
从classloader到单例
单例是一种设计模式。表明上看好像和classloader没有什么关系。所以我们从单例的代码入手开始考虑。
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
上面就单例的一种写法,构造方法设置为private,使用静态方法来获取对象。现在开始和classloader做联系。先想一个问题,是否能造出2个Singleton 对象。大家都这么写单例,貌似是不可以的。我现在自己写两个classloader,并且都有Singleton 的路径,两个loader都去加载初始化Singleton 。此时,内存里就出现了两个Singleton 对象。由于是两个不同的loader加载的,两个对象不能互相引用。那是否找个方式可以互相引用呢?下来骚操作出来了。给类加一个接口。
public class Singleton implements SingletonInterface {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
大家都知道双亲委托,现在有两个自定义的loader有Singleton 的路径,他们有共同的父loader,父loader可以加载到SingletonInterface 。次数两个的Singleton 都可以赋值给SingletonInterface 了。现在就可以使用到了两个单例类。他们都是Singleton ,但又不都是同一个Singleton。你也可以说在jvm里, Singleton 不是单例了,你可以拿到多个Singleton 实例,而且还都可以做操作。
从classloader到类隔离
类隔离的用法算是classloder的最常见的用法了。尤其是在web容器中。webappclassloader是打破双亲委托的。都是先找自己loader的路径,再找父。达到的效果就是webapp下有多个项目,每个里面有相同的数据库驱动,但是版本不一样,他们都各自连接对应的数据库。这种情况并不会出现类加载混乱,都保证了每个项目下的lib目录优先,达到了类隔离的效果。
从classloader到热部署
如果是项目级别的热部署,那么web容器也做到了,例如使用weblogic去上传war应用,weblogic不需要停止,就可以把项目加载起来,就是靠新建一个classloader的获取新的资源,然后加载。这里再介绍一种一个项目内的热部署。
目的:接口和实现分离,达到可以热替换实现的地步,有点类似于我们电脑的鼠标,键盘——热插拔。
如何设计呢。这里必须参考一下spring的aop了。spring aop是生成了代理类的,为什么你运行的时候没有察觉呢。得益于他的ioc。spring管理了你的对象,所以在你操作的时候,给你的对象其实是代理后的类对象。那么想法也比较明朗了。我们需要一个ioc的功能,构建一个map。客户端调用的时候,根据接口来调用,每次调用都需要从map中获取。当想更改一些接口的实现的时候。可以通过某种介质来触发,例如配置文件,利用目录监控或者轮询来获取最新的配置,配置项就是接口和实现类的对于关系,这里是不是有点眼熟,确实是spi的玩法。只不过我们可以直接打包新的类按照配置就可以做到不重启,更改类的实现。代码实现如下,有兴趣的可以看看
https://github.com/xpbob/HotSwap
共同学习,写下你的评论
评论加载中...
作者其他优质文章