Mainstream logging technology framework

  • log4j
  • JUL(java.util.logging)
  • JCL(org.apache.commons.logging)
  • slf4j

Log4J

Apache Log4j is a Java-based logging tool. It was invented by Ceki Gulcu. Log4j is one of several Java logging frameworks.

  1. The introduction of the jar package

    <dependency>    
        <groupId>log4j</groupId>    				 		
        <artifactId>log4j</artifactId>    					
        <version>1.2.17</version>
    </dependency>
    Copy the code
  2. Add Log4j file configuration

    log4j.rootLogger=INFO,stdout
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.target=System.out
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d (%t) [%p - %l] %m%n 
    Copy the code
  3. import org.apache.log4j.Logger;
    Logger logger = Logger.getLogger("log4j");
    logger.info("log4j");
    Copy the code

JUL

Official logging implementation since Java1.4.

  1. import java.util.logging.Logger;
    Logger logger = Logger.getLogger("JUL");
    logger.info("JUL");
    Copy the code

JCL

JCL is a technical framework for facade patterns, which do not log directly, but log through a third party (use log4j to print if you have log4j, use JUL if you do not).

  1. <dependency>    
        <groupId>commons-logging</groupId>    				
        <artifactId>commons-logging</artifactId>    		
        <version>1.2</version>
    </dependency>
    Copy the code
  2. import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    Log log = LogFactory.getLog("JCL");
    log.info("JCL");
    Copy the code
  3. When adding the LOG4j JAR package

      <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>1.2.17</version>
       </dependency>
    Copy the code

Analysis of the

The logging framework through the circular array to determine choose org.apache.com mons. Logging. Impl. LogFactoryImpl# discoverLogImplementation

for(int i=0; i<classesToDiscover.length && result == null; ++i) {    
	result = createLogFromClass(classesToDiscover[i], logCategory, true);
}
Copy the code

Build the static immutable group classesToDiscover as the name of the class that the logging adapter is trying to load (in order).

private static final String[] classesToDiscover = {
	"org.apache.commons.logging.impl.Log4JLogger"."org.apache.commons.logging.impl.Jdk14Logger"."org.apache.commons.logging.impl.Jdk13LumberjackLogger"."org.apache.commons.logging.impl.SimpleLog"
};
Copy the code

Org.apache.com log object is obtained by reflection mons. Logging. Impl. LogFactoryImpl# createLogFromClass print output

Class c;
c = Class.forName(logAdapterClassName, true, currentCL);
constructor = c.getConstructor(logConstructorSignature);
Object o = constructor.newInstance(params);
Copy the code

slf4j

Similar to Commons Logging, it is a simple Java Logging facade with no Logging implementation of its own. (Simple Logging Facade for Java, abbreviated Slf4j).

binder

Bound organ network link

  1. <dependency>    
    	<groupId>org.slf4j</groupId>    
    	<artifactId>slf4j-api</artifactId>    
    	<version>1.7.25</version>
    </dependency>
    Copy the code
  2. import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    Logger logger = LoggerFactory.getLogger("slf4j");
    logger.info("slf4j");
    Copy the code
  3. An error. There is no defaultlogger implementation

  4. There is no default binder. The logging framework needs to be bound at deployment time

5.1 Adding a binder and binding it to JUL You don’t need to change the code, just add the JAR package.

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.7.25</version>
</dependency>
Copy the code

5.2 Adding a binder to bind to Log4j You don’t need to change the code, just add the JAR package.

<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-log4j12</artifactId>
   <version>1.7.25</version>
 </dependency>
Copy the code

6.1

6.2

7. Here

bridge

Bridge organ network links

  1. Use log4j to print logs.

    import org.apache.log4j.Logger;
    Logger logger = Logger.getLogger("log4j");
    logger.info("bridge test");
    Copy the code

  2. Use the bridge to change to SLF4J. Bind SLF4J to JUL

     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>log4j-over-slf4j</artifactId>
       <version>1.7.25</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-jdk14</artifactId>
       <version>1.7.25</version>
     </dependency>
    Copy the code
  3. Since SLF4J is bound to JUL, JUL outputs logs

4. The graphic

Spring’s logging technology

Spring4 log

Spring4’s 4.0.9.RELEASE relies on common-logging and uses JCL logging.

Logs are printed during startup

If you joinLOG4JThe jar package

Spring5 log

Spring5’s 5.0.9.RELEASE relies on Spring-JCL

Logs are printed during startup

Spring-jcl

First, we find where Spring prints logsorg.springframework.context.support.AbstractApplicationContext#prepareRefresh

Find logger is protected final Log Logger = logFactory.getlog (getClass()); Get.

Select different log representations through the Switch. Due to theprivate static LogApi logApi = LogApi.JUL;JCL is used by defaultWhen slf4j, log4j 2.x is in the project, Spring selects log4j 2.x. Use loadClass to find this class and modify it if you find it. When you call getLog, you get the concrete implementation

Log difference between Spring4 and Spring5

Spring4 uses JCL to output logs. JCL provides arraysString[] classesToDiscover, which holds the name of the logging adapter’s class. By default, the logging framework used is determined in array order, the class is determined by reflection, and the log object is created by constructor.

Spring5 uses Spring-JCL to output logs. Spring-jcl underlying uses switch to select different logging implementations. JCL is used by default. When there is log4j 2.x, slf4j in the project, use loadClass to find the classes in the order log4j 2.x, slf4j. Change the default values as you find them. When you call getLog, you get the concrete implementation