SLF4J es una capa de abstracción del marco log, que une marcos de registro específicos, como log4j, logback, la API de registro de Java, etc. SLF4J también tiene su propia implementación predeterminada, pero aún utilizamos principalmente SLF4J como la capa de abstracción del marco log.
Para usar SLF4J, debe incluir una dependencia de "org.slf4j: slf4j-api".
Una revisión simple del patrón de fachada
SLF4J es una aplicación típica del modo de fachada, por lo que antes de hablar sobre SLF4J, revisemos brevemente el modo de fachada.
Modo de fachada, cuyo núcleo es que la comunicación con un subsistema debe llevarse a cabo a través de un objeto de apariencia unificado, lo que hace que el subsistema sea más fácil de usar. La estructura del patrón de la tienda se usa para representar una imagen:
El núcleo del modo de fachada es la fachada, es decir, el objeto de la fachada, y el núcleo del objeto de la fachada es de varios puntos:
En términos generales, solo revisar el modo de la tienda es suficiente aquí, y comenzará a aprender sobre SLF4J a continuación.
¿Por qué usamos slf4j?
¿Por qué usamos SLF4J? Por ejemplo:
Usamos logback en nuestro propio sistema
Nuestro sistema usa A.JAR, y el sistema de registro utilizado en A.JAR es log4j
Nuestro sistema usa B.Jar nuevamente, y el sistema de registro utilizado en B.jar es SLF4J-Simple
De esta manera, nuestro sistema tiene que admitir y mantener tres marcos de registro: logback, log4j y slf4j-simple al mismo tiempo, lo cual es muy inconveniente.
La forma de resolver este problema es introducir una capa de adaptación, que determina qué sistema de registro usar, y la persona que llama solo debe hacer es imprimir el registro sin preocuparse por cómo imprimir el registro. SLF4J o el registro de los bienes comunes es esta capa de adaptación, y SLF4J es el objeto de esta investigación en documento.
De la descripción anterior, debemos saber claramente una cosa: SLF4J es solo un estándar de registro, no una implementación específica del sistema de registro. Es muy importante comprender esta oración. SLF4J solo menciona hacer dos cosas:
SLF4J-Simple y Logback son implementaciones específicas de SLF4J. LOG4J no implementa directamente SLF4J, pero hay un puente especial de primera capa SLF4J-LOG4J12 para implementar SLF4J.
Para comprender mejor SLF4J, primero miramos los ejemplos y luego leemos el código fuente. Creo que los lectores tendrán una comprensión más profunda de SLF4J.
Ejemplo de la aplicación SLF4J
Como se mencionó anteriormente, la implementación directa/indirecta de SLF4J incluye SLF4J-Simple, Logback, SLF4J-LOG4J12. Primero definamos un pom.xml e presentemos el paquete JAR relevante:
< xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xsi: schemalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.0.xsd" <ModelVersion> 4.0.0 </modelversion> <MoupRoid> org.xrq.log </groupid> <artifactid> log-test </artifactid> <versión> 1.0.0 </versión> <packaging> jar </paquete> <name> log-test </slis> http://maven.apache.org </url> <producties> <Project.Build.SourceEncoding> UTF-8 </project.Build.SourceEncoding> </propiedades> <pendencies> <Spendency> <MoupRupid> Junit </GroupId> <AtifactId> Junit </ArtifactId> <Version> 4.11 </Version> <cope> test </cope> </pendency> <pendency> <artifactid> slf4j-api </arfactid> <verserse> 1.7.25 </verversion> </pendency> <pendency> <uproupid> ch.qos.logback </groupid> <artifactid> logback-classic </artifactid> <version> 1.2.3 </versión> </dependency> <epelepentency> <grupiD> org.slf4j </groupd </groupid> <artifactid> slf4j-simple </artifactid> <versión> 1.7.25 </versión> </pendency> <pendency> <proupid> log4j </groupid> <artifactid> log4j </arfactid> <versión> 1.2.17 </versión> </pendency> <pendency> <grupid> org.slf4j </groupid> <artifactID> slf4j-log4j12 </artifactid> <versión> 1.7.21 </versión> </pendency> </pendencs> </proyecto>
Escribe un código Java simple:
@Testpublic void testSlf4j () {logger logger = loggerFactory.getLogger (object.class); logger.error ("123"); }A continuación, primero comentamos las líneas 30 a 49 de Pom.xml arriba, es decir, no introducimos ninguna clase de implementación SLF4J y ejecutamos el método de prueba. Echemos un vistazo a la salida de la consola como:
Al ver la salida sin registros, esto verifica nuestra vista: SLF4J no proporciona una implementación específica de registros, y solo SLF4J no puede imprimir registros.
Luego abra la anotación logback-clásica y ejecute el método de prueba. Echemos un vistazo a la salida de la consola como:
Vi que solo necesitamos introducir una clase de implementación específica de SLF4J, y podemos usar el marco de registro para generar el registro.
Finalmente, hacemos una prueba. Abrimos todos los registros, presentamos logback-classic, slf4j-simple, log4j, ejecutamos el método de prueba y la salida de la consola es:
La diferencia de lo anterior es que puede emitir registros, pero se emitirán algunos registros de alarma, lo que nos lleva a introducir múltiples implementaciones SLF4J al mismo tiempo, y luego seleccione uno de ellos como el sistema de registro que usamos.
A partir del ejemplo, podemos sacar una conclusión importante, es decir, el papel de SLF4J: siempre que todo el código use el objeto de fachada SLF4J, no necesitamos preocuparnos por su implementación específica. Al final, una implementación específica se puede usar en todos los lugares, y el reemplazo y el mantenimiento son muy convenientes.
Principio de implementación de SLF4J
He visto el ejemplo SLF4J anterior, y estudiaré la implementación de SLF4J a continuación. Solo nos centraremos en el código clave.
El uso de SLF4J es una oración que permanece sin cambios durante todo el año, "logger logger = loggerFactory.getLogger (object.class);", que muestra que esto se debe usar loggerFactory para obtener la implementación específica de una interfaz de logger proporcionada por SLF4J. El método getLogger de loggerFactory se implementa como:
public static logger getLogger (class <?> clazz) {logger logger = getLogger (clazz.getName ()); if (detect_logger_name_mismatch) {class <?> autoCompuedCallingClass = util.getCallingClass (); if (autocompuedCallingClass! = NULL && NonterChingClasses (Clazz, autoCompuedCallingClass)) {util.Report (String.Format ("Detected Logger Name Mismatch. Util.report ("Ver" + logger_name_mismatch_url + "para una explicación"); }} return logger;}Comience con el código desde la línea 2 y siga el método bind () a loggerFactory:
Private final estático void bind () {try {set <sl> staticloggerBinderPathSet = null; // omita el cheque en Android, ver también // http://jira.qos.ch/browse/slf4j-328 if (! isandroid ()) {staticloggerBinderPathSet = findposshibblestaticLoggerBinderPathSet (); informarmultipleBindingambiguity (staticloggerBinderPathSet); } // La siguiente línea realiza el enlace staticloggerBinder.getSingleton (); Inicialization_state = exitoso_initialization; reportActualBinding (staticloggerBinderPathSet); FixSubStitUteloggers (); replayEvents (); // Libere todos los recursos en AST_FACTORY AST_FACTORY.CLEAR (); } Catch (noClassDefFoundError ncde) {string msg = ncde.getMessage (); if (MessageContainSorgslf4JimplStaticLoggerBinder (msg)) {inicialization_state = nop_fallback_initialization; Util.report ("No se pudo cargar clase /"org.slf4j.impl.staticloggerbinder/". "); Util.Report ("Implementación de Logger de No-Operation (NOP)"); Util.REPort ("Ver" + NO_STATICLOGGERBINDER_URL + "para más detalles"); } else {fallido binding (ncde); tirar ncde; }} Catch (java.lang.nosuchmethoderror nsme) {string msg = nsme.getMessage (); if (msg! = null && msg.contains ("org.slf4j.impl.staticloggerbinder.getsingleton ()")) {inicialization_state = fallado_initialization; Util.Report ("Slf4j-API 1.6.x (o posterior) es incompatible con este enlace"); Util.Report ("Su encuadernación es la versión 1.5.5 o anterior"); Util.report ("Actualice su enlace a la versión 1.6.x."); } lanzar nsme; } catch (Exception e) {fallido binding (e); tirar nueva IllegalStateException ("falla de inicialización inesperada", e); }}La línea 7 de este lugar es una clave, mire el código:
Settatic Set <URL> findPossiblestaticLoggerBinderPathSet () {// use set en lugar de lista para tratar con el error #138 // Linkedhashset apropiado aquí porque preserva el orden de inserción // durante la iteración SET <URL> staticLoggerBinderPathSet = new LinkedHashset <Url> ();; Pruebe {classloader loggerFactoryClassLoader = loggerFactory.class.getClassLoader (); Enumeración <url> rutas; if (loggerFactoryClassLoader == null) {raths = classLoader.getSymitSresources (static_logger_binder_path); } else {raths = loggerFactoryClassLoader.getResources (static_logger_binder_path); } while (raths.hasmoreElements ()) {url rath = raths.nextelement (); staticloggerBinderPathSet.Add (ruta); }} Catch (IOException IOE) {Util.Report ("Error al obtener recursos de la ruta", IOE); } return staticloggerBinderPathSet;}El punto clave de este lugar es en realidad el código en la línea 12. Al obtenerlogger, irá a classpath para encontrar static_logger_binder_path. El valor static_logger_binder_path es "org/slf4j/impl/staticloggerbinder.class", es decir, todas las implementaciones SLF4J, debajo de la ruta del paquete JAR proporcionado, debe haber "org/slf4j/impl/staticloggerbinder.class". Podemos echar un vistazo:
No podemos evitar introducir múltiples implementaciones de SLF4J en el sistema al mismo tiempo, por lo que el lugar de recepción es un conjunto. Debe tener en cuenta que habrá advertencias cuando la parte anterior presente logback, slf4j-simple y log4j al mismo tiempo que la demostración:
Esto se debe a que hay tres "org/slf4j/impl/staticloggerbinder.class" que existe. En este momento, la declaración de salida de la consola del método ReportMultipleBindingAmambiguity:
Informe de void estático privadoMultipleBindingAncambiguidad (SET <URL> bindPathSet) {if (isambiguueStaticLoggerBinderPathSet (BinderPathSet)) {util.REPort ("La ruta de clase contiene múltiples enlaces SlF4J"); for (ruta de url: bindpathset) {util.report ("encontrado vinculante en [" + ruta + "]"); } Util.REPort ("Ver" + múltiple_bindings_url + "para una explicación."); }}Entonces los internautas pueden preguntar, ¿qué debo hacer si hay tres "org/slf4j/impl/staticloggerbinder.class" al mismo tiempo? En primer lugar, se determina que esto no causará un error en el inicio y, en segundo lugar, durante la compilación, el compilador seleccionará uno de los staticloggerbinder.class para la unión.
Finalmente, StaticLoggerBinder es relativamente simple. Los diferentes staticloggerbinders tienen diferentes implementaciones de GetLoggerFactory. Después de obtener IloggerFactory, llame a GetLogger y obtenga el registrador específico. Puede usar Logger para la salida de registro.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.