java - pattern - ¿Debería declararse un registrador Log4J como transitorio?
log4j2 json configuration example (9)
¿Qué hay de usar un registrador estático? ¿O necesita una referencia de registrador diferente para cada instancia de la clase? Los campos estáticos no están serializados de manera predeterminada; puede declarar explícitamente campos para serializar con una matriz privada, estática y final de ObjectStreamField
llamada serialPersistentFields
. Ver la documentación de Oracle
Contenido agregado: cuando use getLogger(getClass()) , usará el mismo registrador en cada instancia. Si desea usar un registrador separado para cada instancia, debe diferenciar el nombre del registrador en el método getLogger (). por ejemplo, getLogger (getClass (). getName () + hashCode ()). Luego debe usar el atributo transitorio para asegurarse de que el registrador no esté serializado.
Estoy usando Java 1.4 con Log4J.
Parte de mi código implica serializar y deserializar objetos de valor (POJO).
Cada uno de mis POJOs declara un registrador con
private final Logger log = Logger.getLogger(getClass());
El serializador se queja de que org.apache.log4j.Logger no se puede serializar.
Debería usar
private final transient Logger log = Logger.getLogger(getClass());
¿en lugar?
El registrador debe ser estático; esto lo haría no serializable.
No hay ninguna razón para hacer que el registrador no sea estático, a menos que tenga una razón sólida para hacerlo.
Este tipo de casos, particularmente en EJB, generalmente se manejan mejor a través del estado local de subprocesos. Por lo general, el caso de uso es algo así como que tiene una transacción particular que tiene un problema y necesita elevar el registro para depurar esa operación, de modo que pueda generar un registro detallado de la operación problemática. Lleve un estado local de subprocesos en la transacción y utilícelo para seleccionar el registrador correcto. Francamente, no sé dónde sería beneficioso establecer el nivel en una INSTANCIA en este entorno porque el mapeo de instancias en la transacción debe ser una función de nivel de contenedor, no tendrá control de qué instancia se utiliza en un transacción dada de todos modos.
Incluso en los casos en los que se trata de un DTO, generalmente no es una buena idea diseñar el sistema de tal forma que se requiera una instancia específica dada, ya que el diseño puede evolucionar fácilmente de forma que lo haga una mala elección. Podrías venir dentro de un mes y decidir que las consideraciones de eficiencia (almacenamiento en caché u otra optimización de cambio de ciclo de vida) romperán tu suposición sobre el mapeo de instancias en unidades de trabajo.
Hay buenas razones para usar un registrador de instancias. Un muy buen caso de uso es para que pueda declarar el registrador en una superclase y usarlo en todas las subclases (el único inconveniente es que los registros de la superclase se atribuyen a la subclase, pero generalmente es fácil mira eso).
(Como otros han mencionado usar estático o transitorio).
Intente hacer el Logger estático en su lugar. Entonces, no tiene que preocuparse por la serialización porque la maneja el cargador de clases.
Los registradores no son serializables, por lo que debe usar transitorios cuando los almacene en campos de instancia. Si desea restaurar el registrador después de la deserialización, puede almacenar el Nivel (Serie) indide su objeto que se serializa.
O bien declara tu campo de registrador como estático o transitorio.
Ambas formas garantizan que el método writeObject () no intente escribir el campo en la secuencia de salida durante la serialización.
Por lo general, los campos del registrador se declaran estáticos, pero si necesita que sea un campo de instancia, simplemente se declara transitorio, como suele hacerse para cualquier campo no serializable. Tras la deserialización, el campo de registro será nulo, por lo que debe implementar un método readObject () para inicializarlo correctamente.
Si realmente desea adoptar el enfoque transitorio, deberá restablecer el registro cuando se deserialice su objeto. La forma de hacerlo es implementar el método:
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
Los javadocs para Serializable tienen información sobre este método.
Su implementación se verá algo así como:
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
log = Logger.getLogger(...);
in.defaultReadObject();
}
Si no haces esto, el registro será nulo después de deserializar tu objeto.
Si quiere que Logger sea por instancia, entonces sí, querrá hacerlo transitorio si va a serializar sus objetos. Log4J Loggers no son serializables, no en la versión de Log4J que estoy usando de todos modos, así que si no haces que tus campos Logger sean transitorios obtendrás excepciones en la serialización.