Label (Space Separation): Uncategorized
The package where the log function code resides
org.apache.ibatis.logging
Loading order of log module
mybatis does not have its own log module. It uses third-party logs (and jdk has its own logs) Log loading order slf4J_commonsLoging_Log4J2_Log4J_JdkLog
Related code
Declare the loading order in the static code block
public final class LogFactory { //Constructing the selected third-party log component adapter private static Constructor<? extends Log> logConstructor; /** * Marker to be used by logging implementations that support markers */ public static final String MARKER = "MYBATIS"; //Construction Method of Selected Third Party Log Component Adapter private static Constructor<? extends Log> logConstructor; //Automatic scanning log implementation, and third-party log plug-in loading priority is as follows: slf4J commonsLoging Log4J2 Log4J JdkLog static { tryImplementation(LogFactory::useSlf4jLogging); tryImplementation(LogFactory::useCommonsLogging); tryImplementation(LogFactory::useLog4J2Logging); tryImplementation(LogFactory::useLog4JLogging); tryImplementation(LogFactory::useJdkLogging); tryImplementation(LogFactory::useNoLogging); }
Here we use the grammatical sugar of Java 8 The tryImplementation method requires a parameter of type runnable, which is annotated with @Functional Interface, so you can use lambda grammar to abbreviate it. LogConstructor preserves the method of constructing log objects, then creates objects by reflection. When logConstructor == null, the run method calling running is used, then what is run's content?
tryImplementation(LogFactory::useSlf4jLogging); private static void tryImplementation(Runnable runnable) { if (logConstructor == null) {//When a construction method is not executed by a vacant person try { runnable.run(); } catch (Throwable t) { // ignore } } }
LogFactory::useSlf4jLogging The setImplementation method attempts to create a Class (get the constructor by reflection) by passing in lass. If successful, save the constructor to the logConstructor for later use.
public static synchronized void useSlf4jLogging() { setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class); } //Initialize the construction method by specifying the log class private static void setImplementation(Class<? extends Log> implClass) { try { Constructor<? extends Log> candidate = implClass.getConstructor(String.class); Log log = candidate.newInstance(LogFactory.class.getName()); if (log.isDebugEnabled()) { log.debug("Logging initialized using '" + implClass + "' adapter."); } logConstructor = candidate; } catch (Throwable t) { throw new LogException("Error setting Log implementation. Cause: " + t, t); } }
The design pattern adapter pattern used here is different because different log components have different definitions of log info error s and so on. mybatis unifies them into the following levels
package org.apache.ibatis.logging; public interface Log { boolean isDebugEnabled(); boolean isTraceEnabled(); void error(String s, Throwable e); void error(String s); void debug(String s); void trace(String s); void warn(String s);
Let's look at the implementation class of the highest priority log slf4J
package org.apache.ibatis.logging.log4j; import org.apache.ibatis.logging.Log; import org.apache.log4j.Level; import org.apache.log4j.Logger; /** * @author Eduardo Macarron */ public class Log4jImpl implements Log { private static final String FQCN = Log4jImpl.class.getName(); private final Logger log; public Log4jImpl(String clazz) { log = Logger.getLogger(clazz); } @Override public boolean isDebugEnabled() { return log.isDebugEnabled(); } @Override public boolean isTraceEnabled() { return log.isTraceEnabled(); } @Override public void error(String s, Throwable e) { log.log(FQCN, Level.ERROR, s, e); } @Override public void error(String s) { log.log(FQCN, Level.ERROR, s, null); } @Override public void debug(String s) { log.log(FQCN, Level.DEBUG, s, null); } @Override public void trace(String s) { log.log(FQCN, Level.TRACE, s, null); } @Override public void warn(String s) { log.log(FQCN, Level.WARN, s, null); } }
The Embodiment of Logging Function
MyBatis enhances Connection,PreparedStatement,ResultSet through dynamic proxy. Its corresponding implementation is the xxxLogger class.