2009-09-29 12 views
5

Tengo un problema con mi singleton cuando se utiliza en cargadores de varias clases. E.g Singleton accedido por múltiples EJB. ¿Hay alguna manera de crear un singleton que tenga solo una instancia en todo el cargador de clases?¿Cómo crear un singleton verdadero en java?

Estoy buscando una solución java pura ya sea con cargador de clases personalizado o de alguna otra manera.

+0

tal vez eso ayuda: http://stackoverflow.com/questions/70689/efficient -way-to-implement-singleton-pattern-in-java – Chris

+0

¿Qué servidor de aplicaciones estás usando? –

+4

¿Está haciendo su PR su propio blog? Eso es lo que dice tu perfil. Entonces, "Encontré un enlace" es realmente "Escribí esa publicación". – ChssPly76

Respuesta

5

La única forma sería hacer que su clase singleton sea cargada por un solo cargador de clases: coloque ese archivo jar en el bootclasspath, por ejemplo.

Una variable estática está intrínsecamente vinculada al cargador de clases que cargó la clase que contiene esa variable. Es solo la forma en que funciona. Si necesita absolutamente una instancia, necesita que esa clase solo la cargue un cargador de clases.

+0

Utilizamos el servidor Glassfish App y OpenESB como servicio de autobús Enterrprise. Este singleton (un contenedor para JCS Cache para almacenar los resultados de la búsqueda Ldap) es parte de la biblioteca común que se comparte entre múltiples componentes de enlace y EJB. – rjoshi

+0

@rjoshi: ¿Y está cargando el singleton en múltiples cargadores de clases, y puede evitar eso? Si la clase siempre va a estar en varios cargadores de clases, no veo cómo evitar que no sea un singleton "adecuado". –

+0

Y también asegúrese de tener cuidado con la serialización/deserialización. La mejor práctica es, probablemente, evitar que su singleton sea serializable. – CPerkins

5

Los servidores de aplicaciones JavaEE generalmente resuelven este problema configurando el singleton como un "servicio", cuya definición y configuración exacta dependen del servidor de aplicaciones en cuestión.

Por ejemplo, en JBoss podría usar un descriptor xyz-service.xml para configurar un objeto singleton que cuelgue del árbol JNDI o JMX, y los componentes de su aplicación (por ej. Sus EJB) obtendrían el singleton del árbol . Eso lo protege en cierta medida de la semántica del cargador de clases subyacente.

+0

Usamos el servidor Glassfish App y OpenESB como el servicio de autobús Enterrprise. Este singleton es parte de la biblioteca común que se comparte entre múltiples componentes de enlace y EJB. – rjoshi

+2

Bien, descubra cómo crear un servicio JMX en Glassfish y conéctese a ese servicio desde sus componentes. – skaffman

+0

Busqué en Google pero no pude encontrar nada, excepto el soporte de EJB3.1 con la función singleton en Glassfish V3. pero usamos EJB3 con Glassfish 2.1GA. – rjoshi

3

J2EE está diseñado teniendo en cuenta la agrupación en clúster, por lo que cualquier diseño que admita tendrá que funcionar con varias JVM. De su pregunta entiendo que no está preocupado por un entorno agrupado, por lo que una simple inserción en JNDI en su servidor de aplicaciones debería hacerlo. En Glassfish, eso se llama lifecycle listener. Incluso después del arranque, inserte su singleton en JNDI, y luego haga que todo lo demás haga una búsqueda JNDI para encontrarlo.

Tenga en cuenta que GlassFish podría seguir cometiendo un error aquí, en el sentido de que podría serializar la clase a JNDI provocando que obtenga diferentes instancias. Dudo que realmente haga esto dentro de una JVM, pero no lo sabrás hasta que lo pruebes.

La respuesta real es que J2EE es hostil a un singleton verdadero global, y la manera J2EE de resolver el problema es replantear la solución. Algo así como una base de datos para contener valores o algún otro servicio externo que pueda garantizar que solo exista una instancia de los datos (incluso si existen varias instancias de objetos que representan los datos) es la vía J2EE.

+0

Estoy usando este singleton para almacenar el caché ldap. Me pregunto cómo otros desarrolladores están resolviendo estos problemas. – rjoshi

+1

rjoshi, lo haría como una pregunta separada con algunos detalles más técnicos, pero me parece que no es necesario que sea verdaderamente global. Póngalo en JNDI, y si una búsqueda determinada ocurre dos veces, que así sea. – Yishai

+0

@Yishai: thx. para tu sugerencia. Lo probaré y te lo haré saber. Estaba tratando de evitar el contenedor JNDI/EJB y resolver el uso del hacker de clases, pero supongo que esa es la única forma ... – rjoshi

0

para lograr una verdadera Singleton, hay que seguir los siguientes lineamientos:

  1. Haga su clase como final. Otros no pueden sub-clase y crear una instancia más
  2. Hacer la instancia Singleton como private static final
  3. Proporcionar private constructor y public getInstance() método.
  4. Asegúrese de que esta clase Singleton se carga por one ClassLoader only
  5. anulación readResolve() método y regresar misma instancia sin crear nueva instancia en el proceso de de-serialización.

Código de ejemplo:

final class LazySingleton { 
    private LazySingleton() {} 
    public static LazySingleton getInstance() { 
     return LazyHolder.INSTANCE; 
    } 
    private static class LazyHolder { 
     private static final LazySingleton INSTANCE = new LazySingleton(); 
    } 
    private Object readResolve() { 
     return LazyHolder.INSTANCE; 
    } 
} 

Consulte a continuación pregunta SE para más detalles:

What is an efficient way to implement a singleton pattern in Java?

Cuestiones relacionadas