1. Общ преглед
Когато използваме SLF4J в нашите приложения, понякога виждаме предупредително съобщение за множество обвързвания в пътя на класа, отпечатан на конзолата.
В този урок ще се опитаме да разберем защо виждаме това съобщение и как да го разрешим.
2. Разбиране на предупреждението
Първо, нека разгледаме примерно предупреждение:
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:.../slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:.../logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See //www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
Това предупреждение ни казва, че SLF4J е намерил две обвързвания. Единият е в slf4j-log4j12-1.7.21.jar, а другият в logback-classic-1.1.7.jar .
Нека сега разберем защо виждаме това предупреждение.
Simple Logging Facade за Java (SLF4J) служи като проста фасада или абстракция за различни системи за регистриране. По този начин тя ни позволява да включим желаната рамка за регистриране по време на разполагане.
За да постигне това, SLF4J търси обвързвания (известни също като доставчици) в пътя на класа. Обвързванията са основно реализации на определен клас SLF4J, предназначени да бъдат разширени, за да се включи специфична рамка за регистриране.
По дизайн SLF4J ще се свързва само с една регистрационна рамка наведнъж. Следователно, ако на пътя на класа присъстват повече от едно свързване, то ще излъчи предупреждение .
Струва си да се отбележи, че вградените компоненти като библиотеки или рамки никога не трябва да декларират зависимост от някакво свързване на SLF4J. Това е така, защото когато библиотеката декларира зависимостта по време на компилиране от свързване SLF4J, тя налага това свързване на крайния потребител. Очевидно това отрича основната цел на SLF4J. Следователно те трябва да зависят само от библиотеката slf4j-api .
Също така е важно да се отбележи, че това е само предупреждение. Ако SLF4J намери множество обвързвания, той ще избере една регистрационна рамка от списъка и ще се свърже с нея. Както се вижда на последния ред на предупреждението, SLF4J избра Log4j, като използва org.slf4j.impl.Log4jLoggerFactory за действителното свързване.
3. Намиране на конфликтни JAR
Предупреждението изброява местоположенията на всички обвързвания, които намери. Обикновено това е достатъчна информация за идентифициране на безскрупулната зависимост, която преходно привлича нежелано свързване на SLF4J в нашия проект.
Ако не е възможно да се идентифицира зависимостта от предупреждението, можем да използваме зависимостта: tree maven goal:
mvn dependency:tree
Това ще покаже дървото на зависимостите за проекта:
[INFO] +- org.docx4j:docx4j:jar:3.3.5:compile [INFO] | +- org.slf4j:slf4j-log4j12:jar:1.7.21:compile [INFO] | +- log4j:log4j:jar:1.2.17:compile [INFO] +- ch.qos.logback:logback-classic:jar:1.1.7:compile [INFO] +- ch.qos.logback:logback-core:jar:1.1.7:compile
Използваме Logback за влизане в нашето приложение. Следователно, ние нарочно добавихме връзката Logback, присъстваща в класическия JAR за регистрация . Но зависимостта на docx4j също е включила друго свързване с JAR на slf4j-log4j12 .
4. Резолюция
Сега, след като знаем обидната зависимост, всичко, което трябва да направим, е да изключим slf4j-log4j12 JAR от зависимостта docx4j :
org.docx4j docx4j ${docx4j.version} org.slf4j slf4j-log4j12 log4j log4j
Тъй като няма да използваме Log4j, може би е добра идея да го изключим.
5. Заключение
В тази статия видяхме как можем да разрешим често вижданото предупреждение за множество обвързвания, издавани от SLF4J.
Изходният код, придружаващ тази статия, е достъпен в GitHub.