web-dev-qa-db-fra.com

Classe Singleton avec plusieurs chargeurs de classe

E.g J'ai la classe Singleton avec le champ statique instance:

public class Singleton {

    private static Singleton instance;

    // other code, construct, getters, no matter    
}

Je peux charger cette classe deux fois avec deux chargeurs de classe différents. Comment pourrais-je l'éviter? C'est dangereux et dangereux. 

De plus, si je mets l'instance à null, le ferait-il à null pour les deux classes?

Singleton singleton = Singleton.getInstance();
singleton = null;
14
lies

Si vous voulez une vraie Singleton sur plusieurs chargeurs de classe, vous avez besoin d'un parent commun pour charger la classe en question, ou vous devez spécifier vous-même le chargeur de classe.

Mise à jour: D'après le commentaire de @Pshemo ci-dessous, une bonne partie du contenu du blog ci-dessous pourrait provenir directement d'un Article JavaWorld . J'ai laissé l'entrée du blog car elle peut toujours aider quelqu'un, mais il est utile de savoir d'où vient le contenu.

Original: Il y a une entrée blog qui vous donne le moyen de le faire "(bien que je ne l'aie pas essayé!), Et cela semble assez raisonnable

Comme demandé ci-dessous, un extrait de code tiré de mon lien ci-dessus - je vous suggère toutefois de consulter le blog pour connaître le contexte complet:

private static Class getClass(String classname) throws ClassNotFoundException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if(classLoader == null) 
        classLoader = Singleton.class.getClassLoader();
      return (classLoader.loadClass(classname));
}
26
Sean Landsman

C'est un hack qui utilise mal le fait que Properties étend Map, une vieille décision de conception malheureuse.

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's 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;
    }
}

Cela pourrait être paramétré, mais l'initialisation serait paresseuse et passerait à getSingleton().

Properties est Hashtable-, il est donc thread-safe (selon la documentation). Donc, on pourrait utiliser props.computeIfAbsent(). Mais je l'aime plus comme ça.

Lisez également ici: Portée des propriétés du système Java

Je viens de l'écrire et il y a une chance que quelque chose que j'aie oublié qui empêche cela de fonctionner.

0
Ondra Žižka