SLF4J는 LOG4J, LOGBACK, Java Logging API 등과 같은 특정 로그 프레임 워크를 바인딩하는 로그 프레임 워크 추상화 레이어입니다. SLF4J는 자체 기본 구현도 있지만 여전히 로그 프레임 워크의 추상화 계층으로 SLF4J를 주로 사용합니다.
SLF4J를 사용하려면 "org.slf4j : slf4j-api"에 의존성을 포함해야합니다.
외관 패턴에 대한 간단한 검토
SLF4J는 Facade 모드의 일반적인 응용 프로그램이므로 SLF4J에 대해 이야기하기 전에 Facade 모드를 간략하게 검토해 봅시다.
서브 시스템과의 커뮤니케이션은 통합 된 외관 객체를 통해 수행되어야한다는 포장 모드입니다. 서브 시스템을보다 쉽게 사용할 수 있습니다. 상점 패턴의 구조는 그림을 나타내는 데 사용됩니다.
외관 모드의 핵심은 외관, 즉 정면 물체 및 외관 객체의 핵심은 다음과 같습니다.
일반적으로, 상점 모드를 검토하는 것만으로는 여기에서 충분하며 다음에 SLF4J에 대해 배우기 시작할 것입니다.
SLF4J를 사용하는 이유는 무엇입니까?
SLF4J를 사용하는 이유는 무엇입니까? 예를 들어:
우리는 자체 시스템에서 로그백을 사용합니다
우리의 시스템은 a.jar를 사용하고 A.jar에 사용되는 로그 시스템은 log4j입니다.
우리 시스템은 B.jar를 다시 사용하고 B.jar에 사용되는 로그 시스템은 Slf4j-simple입니다.
이런 식으로, 우리의 시스템은 로그백, log4j 및 slf4j-simple의 세 가지 로그 프레임 워크를 지원하고 유지해야하며, 이는 매우 불편합니다.
이 문제를 해결하는 방법은 사용할 로그 시스템을 결정하는 적응 계층을 소개하는 것입니다. 호출자는 로그를 인쇄하는 방법에 대한 관심없이 로그를 인쇄하는 것입니다. SLF4J 또는 Commons-Logging 은이 적응 계층이며 SLF4J는이 논문 연구의 대상입니다.
위의 설명에서 우리는 한 가지를 명확하게 알아야합니다. SLF4J는 로깅 시스템의 특정 구현이 아니라 로깅 표준 일뿐입니다. 이 문장을 이해하는 것이 매우 중요합니다. SLF4J는 두 가지 일만 언급합니다.
SLF4J-Simple 및 Logback은 SLF4J의 특정 구현입니다. LOG4J는 SLF4J를 직접 구현하지는 않지만 SLF4J를 구현하기위한 특별한 1 층 브리지 SLF4J-LOG4J12가 있습니다.
SLF4J를 더 잘 이해하기 위해 먼저 예제를보고 소스 코드를 읽습니다. 나는 독자들이 SLF4J에 대해 더 깊이 이해할 것이라고 믿는다.
SLF4J 응용 프로그램 예제
위에서 언급 한 바와 같이, SLF4J의 직접/간접적 구현에는 SLF4J-Simple, Logback, SLF4J-LOG4J12가 포함됩니다. 먼저 pom.xml을 정의하고 관련 JAR 패키지를 소개하겠습니다.
<!-오리지널 텍스트 : 5 월의 Cangjie http://www.cnblogs.com/xrq730/p/8619156.html-> <project xmlns = "http://maven.apache.org/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.0.xsd" <modeversion> 4.0.0 </modelversion> <groupid> org.xrq.log </groupid> <artifactid> log-test </artifactid> <version> 1.0.0 </version> </packaging> <name> log-test </name> <url> http://maven.apache.gorg </url> <project.build.sourceencoding> utf-8 </project.build.sourceencoding> </properties> <pectionies> <pectionency> <groupid> junit> <artifactid> junit </artifactid> <scope> <copope> </scope> </dependency> <pelection> <groupid> org.slf4j </groupid> <artifactid> slf4j-api </artifactid> <bersion> 1.7.25 </version> </fectionency> <pectionement> <groupid> ch.qos.logback </groupid> <artifactid> logback classic </eppendency> 1.3 </version> </rependency> <groupid> org.slf4j </groupid> <artifactid> slf4j-simple </artifactid> <bersion> 1.7.25 </version> </fectionency> <prectionency> <groupid> log4j </groupid> <artifactid> log4j </artifactid> version> 1.2.17 </dependency> <groupid> org.slf4j </groupid> <artifactid> slf4j-log4j12 </artifactid> <bersion> 1.7.21 </version> </fectionency> </sectovencies> </project>
간단한 자바 코드 작성 :
@testpublic void testslf4j () {logger logger = loggerfactory.getLogger (object.class); logger.error ( "123"); }다음으로, 우리는 먼저 위의 pom.xml의 30 ~ 49 행을 언급합니다. 즉, SLF4J 구현 클래스를 소개하지 않고 테스트 방법을 실행합니다. 콘솔의 출력을 다음과 같이 살펴 보겠습니다.
로그가없는 출력을보고, 이것은 우리의 견해를 확인합니다. SLF4J는 로그의 특정 구현을 제공하지 않으며 SLF4J 만 로그를 인쇄 할 수 없습니다.
그런 다음 로그 백 클래스 주석을 열고 테스트 방법을 실행하십시오. 콘솔의 출력을 다음과 같이 살펴 보겠습니다.
SLF4J의 특정 구현 클래스를 소개해야하며 로그 프레임 워크를 사용하여 로그를 출력 할 수 있습니다.
마지막으로 테스트를 수행합니다. 모든 로그를 열고 로그 백 클래스, SLF4J-Simple, Log4J, 테스트 방법을 실행하며 콘솔 출력이 다음과 같습니다.
위의 차이점은 로그를 출력 할 수 있지만 일부 경보 로그가 출력되어 동시에 여러 SLF4J 구현을 도입 한 다음 사용하는 로그 시스템으로 선택할 수 있습니다.
이 예에서, 우리는 중요한 결론, 즉 SLF4J의 역할을 도출 할 수 있습니다. 모든 코드가 Facade Object SLF4J를 사용하는 한 특정 구현에 신경 쓰지 않아도됩니다. 결국, 하나의 특정 구현이 모든 장소에서 사용될 수 있으며 교체 및 유지 보수가 매우 편리합니다.
SLF4J 구현 원리
위의 SLF4J 예제를 살펴 보았고 아래에서 SLF4J의 구현을 연구하겠습니다. 우리는 키 코드에만 초점을 맞출 것입니다.
SLF4J의 사용은 1 년 내내 변경되지 않은 문장으로, "logger = loggerfactory.getLogger (Object.Class);"는 LoggerFactory를 사용하여 SLF4J가 제공하는 Logger 인터페이스의 특정 구현을 얻는 것임을 보여줍니다. loggerfactory의 getLogger 메소드는 다음과 같이 구현됩니다.
public static logger getLogger (class <?> clazz) {logger logger = getLogger (clazz.getName ()); if (detect_logger_name_mismatch) {class <?> autocomputedCallingClass = util.getCallingClass (); if (autocomputedCallingClass! = null && nonmatchingclasses (Clazz, autocomputedCallingClass)) {util.report (string.format ( "감지 된 로거 이름 불일치. util.report ( "설명은" " + logger_name_mistatch_url +"참조 "); }} return logger;}라인 2의 코드로 시작하여 bind () 메소드를 따라 loggerFactory를 사용하십시오.
개인 최종 정적 void bind () {try {set <url> staticLoggerBinderPathSet = null; // Android에서 확인을 건너 뛰고 // http://jira.qos.ch/browse/slf4j-328 if (! isandroid ()) {staticloggerbinderpathset = findpossiblestaticLoggerBinderPathset (); reportmultiplebindingambiguity (staticLoggerBinderPathSet); } // 다음 줄에는 바인딩 staticLoggerBinder.getSingleton (); 초기화 _state = success_initialization; reportActualBinding (staticLoggerBinderPathSet); FixSubStitUteLoggers (); ReplayEvents (); // 모든 리소스를 SORD_FACTORY SUBSER_FACTORY.CLEAR ()에 해제합니다. } catch (noclassDeffoundError ncde) {문자열 msg = ncde.getMessage (); if (messagecontainsorgslf4jimplstaticloggerbinder (msg)) {initialization_state = nop_fallback_initialization; util.report ( "클래스 /"org.slf4j.impl.staticloggerbinder/"를로드하지 못했습니다. "); util.report ( "No-Operation (NOP) 로그 구현에 대한 기본값"); util.report ( " + no_staticloggerbinder_url +"를 참조하십시오. 자세한 내용은 "); } else {실패한 바인딩 (ncde); NCDE를 던지십시오. }} catch (java.lang.nosuchmethoderror nsme) {string msg = nsme.getmessage (); if (msg! = null && msg.contains ( "org.slf4j.impl.staticloggerbinder.getsingleton ()))) {initialization_state = feailing_initialization; util.report ( "SLF4J-API 1.6.x (또는 이후)는이 바인딩과 호환되지 않습니다."); util.report ( "바인딩은 버전 1.5.5 이하입니다."); util.report ( "바인딩을 버전 1.6.x로 업그레이드"); } 던지기 NSME; } catch (예외 e) {실패한 바인딩 (e); 새로운 불법 상태 외환 ( "예기치 않은 초기화 실패", e)를 던지십시오. }}이 장소의 7 행은 핵심입니다. 코드를보십시오.
정적 세트 <Url> findPossiBlestaticLoggerBinderPathset () {// BUG #138 // 링크드 하시 세트 반복 중에 삽입 순서가 보존되기 때문에 적절한 버그 #138 // 링크드 하시 세트 <URL> staticLoggerBinderPathSet = new LinkedHashSet <Url> ()를 처리하기 때문에 목록 대신 세트를 사용합니다. {classloader loggerFactoryClassLoader = loggerFactory.class.getClassLoader (); 열거 <Url> 경로; if (loggerFactoryClassLoader == null) {paths = classload.getSystemResources (static_logger_binder_path); } else {paths = loggerFactoryClassLoader.getResources (static_logger_binder_path); } while (paths.hasmoreElements ()) {url path = paths.nextElement (); staticLoggerBinderPathSet.Add (경로); }} catch (ioexception ioe) {util.report ( "경로에서 자원을 얻는 오류", ioe); } return staticLoggerBinderPathSet;}이 장소의 핵심 요점은 실제로 12 행의 코드입니다. static_logger_binder_path 값은 "org/slf4j/empl/staticloggerbinder.class"입니다. 우리는 다음을 살펴볼 수 있습니다.
시스템에서 동시에 여러 SLF4J 구현을 도입하지 않으므로 수신 장소는 세트입니다. 위의 부분이 데모와 동시에 로그백, SLF4J-Simple 및 LOG4J를 소개 할 때 경고가있을 것입니다.
여기에는 존재하는 3 개의 "org/slf4j/empl/staticloggerbinder.class"가 있기 때문입니다. 현재 보고서 MultipleBindingAmbiguity 메소드 콘솔 출력 문 :
개인 정적 void void reportmultiplebindingambiguity (set <url> bindpathset) {if (isambiguousStaticLoggerBinderPathSet (binderPathSet)) {util.report ( "클래스 경로가 다중 slf4j 바인딩을 포함합니다."); for (url path : bindpathset) {util.report ( "[" + path + "]에서 찾은 바인딩; } util.report ( "설명은" " + multip_bindings_url +"참조 "); }}그런 다음 네티즌은 "org/slf4j/empl/staticloggerbinder.class"가 동시에 있으면 어떻게해야합니까? 우선, 이것은 시작에 오류가 발생하지 않을 것이며, 둘째, 컴파일 중에 컴파일러는 바인딩을 위해 staticLoggerBinder.class 중 하나를 선택합니다.
마지막으로 STATICLOGGERBINDER는 비교적 간단합니다. 다른 staticLoggerBinders는 GetLoggerFactory의 구현이 다릅니다. iloggerFactory를 얻은 후 GetLogger를 호출하고 특정 로거를 얻으십시오. 로그 출력에 로거를 사용할 수 있습니다.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.