多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計劃對“設計模式”進行修訂,其中提到了要剔除“單例模式”,很期待修訂版早點出來。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章