JCL, called the "Jakarta Commons Logging", also known as "Apache Commons Logging", is a common log API Apache provides. JCL using design mode "adapter mode", which is a unified interface "All Java logging achieve" provided, then the class will be operating in the adaptation entrusted to specific logging framework logs, it itself It provides an implementation of a log , but is very weak ( SimpleLog ). It is generally not use it alone. It allows developers to use different tools to achieve specific log: Log4j, jdk own log (JUL)
There are two basic JCL abstract class: Log (basic recorder) and LogFactory (responsible for creating Log instances)
Log inheritance system shown in Figure 1:
LogFactory inheritance system shown in Figure 2:
Log4JLogger, Jdk14Logger and so is adaptation class.
In Log4JLogger class contains "org.apache.log4j.Logger" type, i.e. in Log4J Logger class, method of operation and thus call log Log4JLogger class will be delegated to "org.apache.log4j.Logger" Class run
in Jdk14Logger class contains "java.util.logging.Logger" categories, namely Java logging API in the Logger class, which calls for logging method of operation Jdk14Logger class will be entrusted to the "java.util.logging. Logger "class run
"Jcl and jul, log4j1, log4j2, logback integration": https://jybzjf.iteye.com/blog/2238792
"Commons-Logging Detailed existing ClassLoader problem": https://yq.aliyun.com/articles/46888
A, JCL entry
JCL + Java Logging API project to build:
1. Build maven project: JCL jar package
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
2. Create TestDemo: JCL interface no other logging implementations, the native jdk will automatically log (JUL)
@Test
public void testQuick() throws Exception{
// 获取log日志记录器对象
Log log = LogFactory.getLog(JCLTest.class);
// 日志记录输出
log.info("hello jcl");
}
JCL + Log4J project to build:
1. JCL interface log4j log
First, add a jar package log4j logs implemented in the Maven project
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
The contents of the configuration file and log4j.properties commons-logging.properties 2. Then the two files created
log4j.properties configuration file as follows:
#配置根 Loggers控制日志的输出级别与日志是否输出
log4j.rootLogger=trace,console
#配置输出到控制台 Appenders是指定日志的输出方式
log4j.appender.console=org.apache.log4j.ConsoleAppender
#指定输出控制台
log4j.appender.console.Target = System.out
#指定布局,输出日志的格式
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#指定布局的参数
log4j.appender.console.layout.ConversionPattern=[%-10p] %r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
commons-logging.properties configuration file as follows:
org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger
3. Finally Demo test, JCL calls log4j achieve, be achieved log4j logging
@Test
public void testQuick() throws Exception{
// 获取log日志记录器对象
Log log = LogFactory.getLog(JCLTest.class);
// 日志记录输出
log.info("hello jcl");
}
commons-logging achieve binding log
LogFactory.getLog (JclTest.class) source as follows:
public static Log getLog(Class clazz) throws LogConfigurationException {
return getFactory().getInstance(clazz);
}
Log of the acquired process is roughly divided into two stages
- Get LogFactory process (literally Log is the production plant). commons-logging LogFactory default implementation provided by: LogFactoryImpl
- Log acquisition process according to LogFactory. commons-logging implementation provides a default Log: Jdk14Logger, Log4JLogger, SimpleLog.
Probably look at the contents of commons-logging package:
Second, why should we use log facade
1. for interface development, no longer dependent on a specific category. Reduce coupling code
2. project implementation class by introducing different log, the log can flexibly switch the frame
3. unified API, enabling developers to easily learn and use
4. facilitate unified configuration management project log
Three, JCL principle
1. Log implementation class dynamic loading LogFactory
2.1 LogFactory of the acquisition process
LogFactory several ways to get from below
(1) the attribute acquisition system
System.getProperty("org.apache.commons.logging.LogFactory")
(2) using the SPI mechanism java
SPI mechanism for java, the details can search on their own, will not be described here. Search paths are as follows:
META-INF/services/org.apache.commons.logging.LogFactory
Search is simply jar which contains the package contains the search file corresponding to the specified achieve LogFactory
(3) from the commons-logging configuration file
commons-logging also can have its own configuration file, named commons-logging.properties, but currently the most part, we do not have to use it. If the configuration file, attempts to read the attribute "org.apache.commons.logging.LogFactory" from a value corresponding to the configuration file
(4) 默认的 org.apache.commons.logging.impl.LogFactoryImpl
LogFactoryImpl 是 commons-logging 提供的默认实现
2.2根据 LogFactory 获取 Log 的过程
这时候就需要寻找底层是选用哪种类型的日志
就以 commons-logging 提供的默认实现为例,来详细看下这个过程:
(1) 从 commons-logging 的配置文件中寻找 Log 实现类的类名
从commons-logging.properties 配置文件中寻找属性为 "org.apache.commons.logging.Log" 对应的 Log 类名
(2) 从系统属性中寻找 Log 实现类的类名
System.getProperty("org.apache.commons.logging.Log")
(3) 如果上述方式没找到,则从 classesToDiscover 属性中寻找
classesToDiscover 属性值如下:
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"
};
3.获取具体的日志实现,通过查看源代码可以发现,执行"LogFactory.getLog(Main.class)"语句的时候,最终是执行LogFactoryImp类中的discoverLogImplementation方法,在该方法中有如下代码语句:
for(int i = 0; i < classesToDiscover.length && result == null; ++i)
{
result = this.createLogFromClass(classesToDiscover[i], logCategory, true);
}
它会尝试根据上述类名,依次进行创建,如果能创建成功,则使用该 Log,然后返回给用户。