O SLF4J é uma camada de abstração da estrutura de log, que vincula estruturas de log específicas, como log4j, logback, API de log Java, etc. SLF4J também possui sua própria implementação padrão, mas ainda usamos principalmente o SLF4J como a camada de abstração da estrutura de log.
Para usar o SLF4J, você deve incluir uma dependência de "org.slf4j: slf4j-api".
Uma revisão simples do padrão de fachada
O SLF4J é uma aplicação típica do modo de fachada; portanto, antes de falar sobre SLF4J, vamos revisar brevemente o modo de fachada.
Modo de fachada, cujo núcleo é que a comunicação com um subsistema deve ser realizada através de um objeto de aparência unificada, facilitando o uso do subsistema. A estrutura do padrão de fã de loja é usada para representar uma imagem:
O núcleo do modo de fachada é fachada, ou seja, o objeto de fachada e o núcleo do objeto de fachada são vários pontos:
De um modo geral, apenas revisar o modo de loja é suficiente aqui e você começará a aprender sobre o SLF4J em seguida.
Por que usamos slf4j
Por que usamos SLF4J? Por exemplo:
Usamos logback em nosso próprio sistema
Nosso sistema usa A.Jar, e o sistema de log usado em A.Jar é log4j
Nosso sistema usa B.jar novamente, e o sistema de log usado em B.jar é Slf4j-simple
Dessa forma, nosso sistema precisa apoiar e manter três estruturas de log: Logback, Log4J e Slf4j-Simple ao mesmo tempo, o que é muito inconveniente.
A maneira de resolver esse problema é introduzir uma camada de adaptação, que determina qual sistema de log para usar, e o chamador só precisa fazer é imprimir o log sem se importar com como imprimir o log. SLF4J ou Loging Commons é essa camada de adaptação, e o SLF4J é o objetivo desta pesquisa em papel.
A partir da descrição acima, devemos saber claramente uma coisa: o SLF4J é apenas um padrão de registro, não uma implementação específica do sistema de registro. É muito importante entender essa frase. SLF4J apenas menciona fazer duas coisas:
Slf4j-simple e Logback são implementações específicas do SLF4J. O LOG4J não implementa diretamente o SLF4J, mas existe uma ponte de primeira camada especial SLF4J-LOG4J12 para implementar o SLF4J.
Para entender melhor o SLF4J, examinamos os exemplos primeiro e depois lemos o código -fonte. Acredito que os leitores terão uma compreensão mais profunda do SLF4J.
Exemplo de aplicação SLF4J
Como mencionado acima, a implementação direta/indireta do SLF4J inclui Slf4j-Simple, Logback, SLF4J-LOG4J12. Vamos primeiro definir um pom.xml e apresentar o pacote JAR relevante:
<!-Texto original: Cangjie em maio http://www.cnblogs.com/xrq730/p/8619156.html-> <projeto xmlns = "http://maven.apache.org/pom/pom/4.0.0" 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.xsd"> <ModelVersion> 4.0.0 </modelversion> <puriid> org.xrq.log </foupiD> <stifactId> log-test </artifactId> <versão> 1.0.0 </version> <bacaging> jar </cataging> <name> log-test </name> <erl> htttp:/maven.apten.ache. <Project.build.sourceEncoding> utf-8 </project.build.sourceEncoding> </sperties> <pendences> <pendesency> <puperid> junit </proupid> <stifactId> junit </stifactId> <Versão> </versuse> <scope> test </scope> </scope> </dependente> </dependente> </dependente> </dependente> </dependente> </scope> </scope> </dependente> </sorpening> </sorfactid> </siper> </socpope> </scope> </scope> </scope> </sorpentid> </sorfactId> <siper> </versuse> </scope> </scope> </scope> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <PuerpId> org.slf4j </groupiD> <TRAFACTID> SLF4J-LOG4J12 </ARTIFACTID> <Versão> 1.7.21 </version> </dependency> </dependências> </projection>
Escreva um código Java simples:
@Testpublic void testslf4j () {logger logger = loggerFactory.getLogger (object.class); Logger.error ("123"); }Em seguida, primeiro comentamos as linhas 30 a 49 do pom.xml acima, ou seja, não introduzimos nenhuma classe de implementação do SLF4J e executamos o método de teste. Vamos dar uma olhada na saída do console como:
Vendo a saída sem logs, isso verifica nossa visão: o SLF4J não fornece uma implementação específica de logs e apenas o SLF4J não pode imprimir logs.
Em seguida, abra a anotação logback-Classic e execute o método de teste. Vamos dar uma olhada na saída do console como:
Vi que precisamos apenas introduzir uma classe de implementação específica do SLF4J e podemos usar a estrutura de log para produzir o log.
Finalmente, fazemos um teste. Abrimos todos os logs, introduzimos o clássico de logback, slf4j-simple, log4j, executamos o método de teste e a saída do console é:
A diferença acima é que você pode produzir logs, mas alguns logs de alarme serão emitidos, levando -nos a introduzir várias implementações SLF4J ao mesmo tempo e, em seguida, selecione um deles como o sistema de log que usamos.
A partir do exemplo, podemos tirar uma conclusão importante, ou seja, o papel do SLF4J: desde que todo o código use o objeto de fachada SLF4J, não precisamos nos preocupar com sua implementação específica. No final, uma implementação específica pode ser usada em todos os lugares, e a substituição e a manutenção são muito convenientes.
Princípio de implementação SLF4J
Eu olhei para o exemplo SLF4J acima e estudarei a implementação do SLF4J abaixo. Vamos nos concentrar apenas no código -chave.
O uso do SLF4J é uma frase que permanece inalterada durante todo o ano, "Logger Logger = LoggerFactory.getLogger (object.class);", que mostra que isso é para usar o LoggerFactory para obter a implementação específica de uma interface logger fornecida pelo SLF4J. O método GetLogger de LoggerFactory é implementado como:
public static logger getLogger (classe <?> clazz) {logger logger = getLogger (clazz.getName ()); if (detect_logger_name_mismatch) {classe <?> automathocomputedCallingClass = util.getCallingClass (); if (AutoComputedCallingClass! = NULL && não -MatchingClasses (clazz, automatizado de callingclass)) {util.report (string.format ("nome de logger detectado. Util.report ("ver" + logger_name_mismatch_url + "para uma explicação"); }} Retornar Logger;}Comece com o código da linha 2 e siga o método bind () para LoggerFactory:
private final estático void bind () {try {set <url> staticLoggerBinderPathSet = null; // Saltar a verificação no Android, consulte também // http://jira.qos.ch/browse/slf4j-328 if (! isandroid ()) {staticLoggerBinderPathSet = findPossiblestaticLoggerBinderPatset (); RelatórioMultiplyBindingABiguity (StaticLoggerBinderPathSet); } // A próxima linha faz o staticLoggerBinder.getSingleton (); Inicialização_state = sucesso_initialization; RelatActualBinding (StaticLoggerBinderPathSet); FIXSUBSTITUTELOGGERS (); rePlayEvents (); // Libere todos os recursos em subest_factory subest_factory.clear (); } catch (noclassDeffoundError ncde) {string msg = ncde.getMessage (); if (MessagEContainsorgslf4jimplstaticLoggerBinder (msg)) {Initialization_state = nop_fallback_initialization; Util.report ("Falha ao carregar a classe /"org.slf4j.impl.staticloggerbinder/" "); Util.report ("Defendendo a implementação do logger sem operação (NOP)"); Util.report ("ver" + no_staticLoggerbinder_url + "para mais detalhes."); } else {falhoubinding (NCDE); jogue ncde; }} catch (java.lang.nosuchmethoderror nsMe) {string msg = nsme.getMessage (); if (msg! = null && msg.contains ("org.slf4j.impl.staticLoggerbinder.getSingleton ()")) {Initialization_state = falha_initialization; Util.report ("slf4j-api 1.6.x (ou posterior) é incompatível com essa ligação"); Util.report ("Sua ligação é a versão 1.5.5 ou anterior."); Util.report ("Atualize sua ligação à versão 1.6.x."); } jogue NSME; } catch (Exceção e) {falhoubinding (e); lançar uma nova ilegalStateException ("falha inesperada de inicialização", e); }}A linha 7 deste lugar é uma chave, observe o código:
Conjunto estático <url> findPossBlestaticLoggerBinderPathSet () {// Use o conjunto em vez de listar para lidar com o bug #138 // LinkedHashSet Apropriado aqui porque preserva a ordem de inserção // durante o conjunto de iteração <url> staticLoggerBinderStySet = new LinkedHashset <url> (); tente {classLoader LoggerFactoryClassLoader = LoggerFactory.class.getClassLoader (); Enumeração <url> Caminhos; if (LoggerFactoryClassLoader == null) {Paths = ClassLoader.getSystemResources (static_logger_binder_path); } else {Paths = LoggerFactoryClassLoader.getResources (static_logger_binder_path); } while (paths.hasMoreElements ()) {URL PATH = PATHS.NEXTELEMENT (); staticLoggerBinderPathSet.add (caminho); }} catch (ioexception ioe) {util.report ("Erro obtendo recursos do caminho", ioo); } retornar staticLoggerBinderPathSet;}O ponto -chave deste local é na verdade o código na linha 12. Ao receber o Logger, você irá ao ClassPath para encontrar static_logger_binder_path. O valor static_logger_binder_path é "org/slf4j/implic/staticloggerbinder.class", ou seja, todas as implementações SLF4J, no caminho do pacote JAR fornecido, deve haver "org/slf4j/implicloggerbinder.class". Podemos dar uma olhada:
Não podemos evitar a introdução de várias implementações SLF4J no sistema ao mesmo tempo, portanto o local de recebimento é um conjunto. Você deve observar que haverá avisos quando a parte acima introduzir logback, Slf4j-simple e log4j ao mesmo tempo que a demonstração:
Isso ocorre porque existem três "org/slf4j/implicLoggerbinder.class" que existe. Neste momento, o relatório Método da Bindingbiguidade do Console da declaração de saída do console:
private estático void reportMultipleBindingABIGUIDADE (SET <RIRL> bindPathSet) {if (isambiguousstaticLoggerBinderPathSet (BinderPathSet)) {util.report ("Classe Path contém várias ligações SLF4J"); for (URL Path: BindPathSet) {util.report ("encontrado encadernação em [" + path + "]"); } Util.report ("Veja" + Multips_bindings_url + "para uma explicação."); }}Então os internautas podem perguntar: o que devo fazer se houver três "org/slf4j/implicloggerbinder.class" ao mesmo tempo? Primeiro de tudo, é determinado que isso não causará um erro na inicialização e, em segundo lugar, durante a compilação, o compilador selecionará um dos staticloggerbinder.class para ligação.
Finalmente, o StaticLoggerBinder é relativamente simples. Diferentes StaticLoggerBinders têm implementações diferentes do getLoggerFactory. Depois de obter o ILoggerFactory, ligue para o GetLogger e obtenha o logger específico. Você pode usar o Logger para saída de log.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.