Одиночный класс с несколькими различными загрузчиками классов
Например, у меня есть класс Singleton
со статическим полем instance
:
public class Singleton {
private static Singleton instance;
// other code, construct, getters, no matter
}
Я могу загрузить этот класс дважды с помощью двух разных загрузчиков классов. Как я мог избежать этого? Это опасно и опасно.
Кроме того, если я установил экземпляр в значение null, будет ли он установлен равным null для обоих классов?
Singleton singleton = Singleton.getInstance();
singleton = null;
Ответы
Ответ 1
Если вы хотите использовать true Singleton
для загрузчиков классов, вам нужен общий родительский объект для загрузки рассматриваемого класса или вам нужно указать загрузчик классов самостоятельно.
Обновление: Из комментария от @Pshemo ниже справедливой части содержимого в блоге ниже может быть получена непосредственно из статьи JavaWorld., Я оставил запись в блоге, так как он все равно может помочь кому-то, но его стоит знать, откуда изначально вышло содержание.
Оригинал:
Есть запись blog, которая дает вам способ сделать это" (хотя я и не пробовал!), И выглядит довольно разумно.
Как указано ниже, фрагмент кода из моей ссылки выше - я предлагаю вам посетить блог, но для полного контекста:
private static Class getClass(String classname) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader == null)
classLoader = Singleton.class.getClassLoader();
return (classLoader.loadClass(classname));
}
Ответ 2
Это хак, неправильно использующий тот факт, что Properties
расширяет Map
, старое неудачное дизайнерское решение.
public final class JvmWideSingleton
{
private static final JvmWideSingleton INSTANCE;
static {
// There should be just one system class loader object in the whole JVM.
synchronized(ClassLoader.getSystemClassLoader()) {
Properties sysProps = System.getProperties();
// The key is a String, because the .class object would be different across classloaders.
JvmWideSingleton singleton = (JvmWideSingleton) sysProps.get(JvmWideSingleton.class.getName());
// Some other class loader loaded JvmWideSingleton earlier.
if (singleton != null) {
INSTANCE = singleton;
}
else {
// Otherwise this classloader is the first one, let create a singleton.
// Make sure not to do any locking within this.
INSTANCE = new JvmWideSingleton();
System.getProperties().put(JvmWideSingleton.class.getName(), INSTANCE);
}
}
}
public static JvmWideSingleton getSingleton() {
return INSTANCE;
}
}
Это можно сделать параметризованным, но тогда инициализация будет ленивой и перейдите к getSingleton()
.
Properties
основан на Hashtable
, поэтому он является потокобезопасным (согласно документации). Таким образом, можно использовать props.computeIfAbsent()
. Но мне это нравится больше.
Также читайте здесь: Область свойств системы Java
Я только что написал это, и есть шанс, что я упустил из виду, что помешало бы этому работать.