多classloader对单例模式的影响

早上看了一篇写单例模式的文章,总结的比较全,可惜仍然没有对单例模式在不同classloader甚至是多个jvm上的分析,在网上搜了一下,找到一个例子并改写如下:

定义一个空接口:
// Null interface, do nothing but you'll see the usage later
public interface IAntiSingleton {
}


定义一个通用的单例模式
public class AntiSingleton implements IAntiSingleton {
private static final AntiSingleton instance = new AntiSingleton();

public static AntiSingleton getInstance() {
return instance;
}
}


继承一个classloader并生成AntiSingleton对象
public class NewClassLoader extends ClassLoader {
public IAntiSingleton createNewOne() throws Exception {
InputStream is = getClass().getResourceAsStream("AntiSingleton.class");
byte[] b = new byte[is.available()];
is.read(b);
Class clz = defineClass(null, b, 0, b.length);
Object o = clz.newInstance();
return (IAntiSingleton) o;
}
}


测试方法:
public class TestAntiSingleton {
public static void main(String[] args) throws Exception {
AntiSingleton instance = AntiSingleton.getInstance();
NewClassLoader loader = new NewClassLoader();
IAntiSingleton newObj = loader.createNewOne();
System.out.println(AntiSingleton.getInstance() == newObj);
}
}
output:
=========
false


[b]总结:[/b]

java中,一个类可以有多个定义,并且这些类名可以相同(但同一个类加载器产生类的类名不能相同)。如果不同类加载器两个类名相同,即使类的定义相同,甚至一个类的定义是由另一个类产生的,这两个类也是不同的类。

这也就是输出结果产生false的原因,因为此时两个类虽然名字相同,但是其实已经不是一个类。此时的单例模式,看起来是失效的。注意上面为什么要用接口,因为此时在程序中直接使用NewClassLoader用AntiSingleton对输出结果进行转型,在运行时就会抛出一个类型转换Exception。

可以想到的一种情况是,tomcat中,可以部署很多项目,各个项目中是可以出现相同的类名的,这就需要不同的classloader分别load生成这些类。

此外,GoF计划对“设计模式”进行修订,其中提到了要剔除“单例模式”,很期待修订版早点出来。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章