Original website:
brief introduction
explain
This article introduces the usage of slf4j this logging framework in Java with examples. It will also introduce relevant knowledge.
Official website
Official website: SLF4J
Official website documents: SLF4J Documentation
slf4j introduction
summary
explain
term | explain |
Noun interpretation | Slf4j: simple log facade for Java. |
effect | Similar to the adapter, you can print directly using the slf4j method, and eventually call the specific log, such as java.util.logging, logback and log4j. |
advantage | After the system changes a log source, there is no need to change the code; Save memory (you can use placeholder {}). |
Configuration method | The log format, recording level and output mode are realized through the configuration of the specific log system. |
Supported logging systems | NOP, Simple,log4j, log4j2, java.util.logging, JCL and logback. |
Timing of binding log implementation library | Bind the real Log library statically at compile time |
Method of switching log system | Just switch the jar package. For example, switch from java.util.logging to log4j, and just replace slf4j-jdk14-xxx.jar with slf4j-log4j12-xxx.jar. |
Differences between slf4j and Commons logging
term | slf4j | commons-logging |
Timing of binding log implementation library | Bind the real Log library statically at compile time. Available in OSGI | Dynamic search mechanism to automatically find out the real log library when the program is running. It uses ClassLoader to find and load log libraries, which makes frameworks like OSGI unable to work normally, because different OSGI plug-ins use their own ClassLoader (this mechanism of OSGI ensures that plug-ins are independent of each other). |
placeholder | You can use placeholder '{}' | Placeholders are not available |
Placeholder for slf4j
Other web sites
Advantages and application principle of slf4j_ Java_winwill2012 blog - CSDN blog
General log usage (take log4j as an example)
java file
import org.apache.log4j.Logger; public class TestLog4j { private static final Logger LOGGER = Logger.getLogger(TestLog4j.class); public static void main(String[] args) { String message = "Hello World."; LOGGER.info("This is a test message: " + message); } }
Disadvantages of this method
1. String addition is a performance consuming operation
2. If the output level of log4j configuration is ERROR, it will not output at all and occupy memory.
The solution to the second disadvantage: add judgment, but it will make the code cumbersome. For example:
if (LOGGER.isInfoEnabled()) { LOGGER.info("This is a test message: " + message); }
The {} placeholder method for slf4j
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestLog4j { private static final Logger LOGGER = LoggerFactory.getLogger(TestLog4j.class); public static void main(String[] args) { String message = "Hello World."; LOGGER.info("This is a test message: {}", message); } }
The {} placeholder is used, and there will be no string splicing operation.
Before producing the string of the final log information, this method will check whether a specific log level is turned on, which not only reduces the memory consumption, but also reduces the CPU time to process the string connection command in advance.
Related source code: slf4j-log4j12-1.6.1. Jar = > log4jloggeradapter
public void debug(String format, Object arg1, Object arg2) { if (logger.isDebugEnabled()) { FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable()); } }
slf4j's package
In the following table, you only need to specify bold dependencies, which will automatically pull other dependencies. You can also force other dependencies to a certain version. Just put other dependencies behind bold dependencies.
package | meaning | Required dependencies |
slf4j-api-xxx.jar | slf4j core interface package | |
slf4j-simple-xxx.jar | slf4jSimpleLogger log implementation package | slf4j-api-xxx.jar=> slf4j-simple-xxx.jar |
slf4j-log4j12-xxx.jar | slf4j calls the 1.2 implementation package of log4j | slf4j-api-xxx.jar=> Slf4j-log4j12-xxx. Jar = > log4j-xxx.jar (version 1.2) |
slf4j-log4j13-xxx.jar | slf4j calls the 1.3 implementation package of log4j | |
slf4j-jdk14-xxx.jar | slf4j calls the implementation package of java.util.logging of JDK (only available after jdk1.4) | slf4j-api-xxx.jar=> slf4j-jdk14-xxx.jar => java.util.logging |
slf4j-nop-xxx.jar | slf4j calls nop (no printing) | slf4j-api-xxx.jar=> slf4j-nop-xxx.jar => /dev/null |
slf4j-migrator-xxx.jar | Help migrate your code to use SLF4J. | |
slf4j-ext-xxx.jar | ||
jul-to-slf4j-xxx.jar | The original jul print code is delegated to slf4j | slf4j-api-xxx.jar=> Jul-to-slf4j-xxx. Jar = > slf4j YYY (example: slf4j-simple-xxx.jar) |
log4j-over-slf4j-xxx.jar | The original log4j code remains unchanged and is output using the slf4j interface | slf4j-api-xxx.jar=> Log4j over slf4j XXX. Jar = > slf4j YYY (example: slf4j simple XXX. Jar) |
jcl-over-slf4j-xxx.jar | The original jcl code remains unchanged and is output using the slf4j interface | slf4j-api-xxx.jar=> Log4j over slf4j XXX. Jar = > slf4j YYY (example: slf4j simple XXX. Jar) |
slf4j-jcl-xxx.jar | The original slf4j code remains unchanged, using jcl output | |
logback-classic-xxx.jar | Upgrade of log4j. Not provided by slf4j. | slf4j-api-xxx.jar=> logback-classic-xxx.jar, logback-core-xxx.jar logback naturally supports slf4j, so no connection layer is required |
Call structure
Slf4j API (interface layer)
|
The connection layer of each log implementation package (slf4j-jdk14, slf4j log4j, etc.)
|
Each log implementation package (implementation layer)
Compatibility issues
1. The connection layer binds a specific implementation layer
For example: slf4j-jdk14.jar or slf4j-log4j12.jar.
2. The version of interface layer and connection layer shall be the same
Mixing different versions of slf4j API (interface layer) and connection layer bindings may cause problems. For example, slf4j api-1.7.19.jar corresponds to slf4j-simple-1.7.19.jar. Using slf4j-simple-1.5.5.jar will not work normally.
3. The client is compatible with any interface layer
From the client's point of view, all versions of slf4j API are compatible. You can use any version of slf4j api.jar. As long as the second item is met, there will be no problem.
bridging
Other web sites
Official website: Bridging legacy APIs
brief introduction
If you are developing the components called by the application and have used JCL, some components may directly call java.util.logging. At this time, you need a bridge (named xxx-over/to-slf4j.jar) to redirect their log output to SLF4J.
The bridge is a fake log implementation tool. For example, when jcl-over-slf4j.jar is put into CLASS_PATH, even if a component originally outputs logs through JCL, it will be "cheated" into SLF4J by jcl-over-slf4j, and then SLF4J will hand over the logs to the specific log implementation tool according to the binder. There are relevant routines below: Example 2 and example 3 below.
What happens when log4j-over-slf4j.jar and slf4j-log4j12-version.jar are placed in the CLASS_PATH at the same time: the log will be kicked around and eventually enter an endless loop, resulting in memory overflow. This is also the case when other packets are forwarded to each other. (log4j-over-slf4j and slf4j-log4j12 are exceptions. log4j-over-slf4 makes an internal judgment to prevent memory overflow: judge whether org.slf4j.impl.Log4jLoggerFactory in slf4j-log4j12 jar package exists. If so, it indicates a conflict. Throw an exception and prompt the user to remove the corresponding jar package. The code is slf4j-log4j12-xxx. Jar = > org.apache.log4j.log4jloggerfac Store = > static field).
slf4j official map
Example
@Slf4j
Each time you write a new class, you need to write: private static final Logger logger = = LoggerFactory.getLogger(Demo.class); concise method: use lombok's @ Slf4j.
step
1. Introduce lombok dependency
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
2. Write @ Slf4j on the class
3. Directly use the log variable
slf4j-simple
java file
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Demo { private static final Logger logger = = LoggerFactory.getLogger(Demo.class); public static void main(String[] args) { logger.info("Hello World"); } }
pom.xml
pom.xml(slf4j-simple)
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency>
test
Compile and run the HelloWorld program. Now there will be the following output on the console:
[main] INFO org.example.a.Demo - Hello World
Note: if slf4j XXX is not configured (for example, dependency is not added), the following error will be reported.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Failure reason: the bound slf4j is not found under the class path
slf4j-log4j12
To provide the log4j.properties configuration file.
rely on
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.30</version> <scope>test</scope> </dependency>
The usage is the same as slf4j simple
jul to slf4j simple
Other web sites
Columns of SLF4j and common logging_java_xiaoxinxiao - CSDN blog
Before conversion: java.util.logging(jul) provided with jdk
java file
Use the java.util.logging(jul) that comes with the jdk.
package com.example; import java.util.logging.Logger; public class HelloWorld { private static final Logger logger = Logger.getLogger(HelloWorld.class.getName()); public static void main(String[] args) { logger.severe("jul severe test"); logger.warning("jul warning test"); logger.info("jul info test"); } }
test
March 06, 2020 9:10:07 am com.example.HelloWorld main
Severe: jul severe test
March 06, 2020 9:10:07 am com.example.HelloWorld main
Warning: jul warning test
March 06, 2020 9:10:07 am com.example.HelloWorld main
Info: jul info test
After conversion: jul goes to slf4j simple
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>mytest</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency> </dependencies> </project>
java file
Add the following statements to the main function:
SLF4JBridgeHandler.removeHandlersForRootLogger(); SLF4JBridgeHandler.install();
java file after adding
package com.example; import org.slf4j.bridge.SLF4JBridgeHandler; import java.util.logging.Logger; public class Demo { private static final Logger logger = Logger.getLogger(Demo.class.getName()); public static void main(String[] args) { SLF4JBridgeHandler.removeHandlersForRootLogger(); SLF4JBridgeHandler.install(); logger.severe("jul severe test"); logger.warning("jul warning test"); logger.info("jul info test"); } }
test
[main] ERROR com.example.Demo - jul severe test [main] WARN com.example.Demo - jul warning test [main] INFO com.example.Demo - jul info test
jcl to slf4j
Before conversion: jcl
java program
package com.example; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Demo { private final static Log logger = LogFactory.getLog(Demo .class); public static void main(String[] args) { logger.debug("DEBUG ..."); logger.info("INFO ..."); logger.error("ERROR ..."); } }
maven dependency
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
configuration file
commons-logging.properties
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
test
[INFO] Demo - INFO ... [ERROR] Demo - ERROR ...
After conversion: jcl to slf4j
Modify maven dependencies only
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency>
test
[main] INFO com.example.Demo - INFO ... [main] ERROR com.example.Demo - ERROR ...
Other web sites
slf4j package instructions -- ITeye blog
SLF4J user manual_ Java_ Goodidea CSDN blog
Relationship between log4j and Commons logging, slf4j - sxfans - ITeye blog