日志之JCL解析(二)

一、前言:

本文只列出重要的知识点,具体如以下3点:
1.JCL是什么?
2.JCL如何使用?
3.JCL加载解析?

二、JCL是什么

JCL是apache的开源项目commons-logging,全称为 “ Jakarta Commons Logging ” ,也可称为 “ Apache Commons Logging ”。
JCL解决了日志框架混乱的原始时代,是首发日志门面的长老人物。

三、JCL如何使用

依赖导入
gradle

1
implementation 'commons-logging:commons-logging:1.2'

maven

1
2
3
4
5
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

程序使用

1
2
3
4
5
6
7
8
9
10
11
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Logger {
static final Log LOG = LogFactory.getLog(Logger.class);//获取日志对象

public static void main(String[] args) {
LOG.info("Hello JCL");//打印普通日志
LOG.info(LOG.getClass());//打印日志对象类路径
}
}

程序执行输出

1
2
3
4
4月 01, 2021 1:33:25 下午 cn.test.log.Logger main
信息: hello jcl
4月 01, 2021 1:33:26 下午 cn.test.log.Logger main
信息: class org.apache.commons.logging.impl.Jdk14Logger

四、JCL加载解析

步骤一:程序代码加载

1
LogFactory.getLog(Logger.class);⬅️

步骤二:LogFacoty

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//获取日志对象
public static Log getLog(final Class clazz) throws LogConfigurationException {
return getFactory().getInstance(clazz);⬅️
}

//获取日志工厂对象(ps:只要没有额外配置都是 " LogFactoryImpl " 对象)
public static LogFactory getFactory() throws LogConfigurationException {
//上下文类加载器
final ClassLoader contextClassLoader = getContextClassLoaderInternal();
//从缓存工厂获取日志工厂对象
LogFactory factory = getCachedFactory(contextClassLoader);
//缓存工厂有直接返回
if (factory != null) {
return factory;
}
// ...
if (factory == null) {
//构建 " LogFactoryImpl " 工厂实现
factory = newFactory(FACTORY_DEFAULT, thisClassLoader, contextClassLoader);⬅️
}
if (factory != null) {
//存入缓存工厂供下一次快速获取
cacheFactory(contextClassLoader, factory);
}
return factory;
}

// 子类实现
public abstract Log getInstance(String name) throws LogConfigurationException;⬅️

步骤三:LogFactoryImpl(默认日志工厂实现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//获取日志实例
@Override
public Log getInstance(final Class clazz) throws LogConfigurationException {
return getInstance(clazz.getName());⬅️
}

@Override
public Log getInstance(final String name) throws LogConfigurationException {
//实例表获取缓存日志实例
Log instance = (Log) instances.get(name);
if (instance == null) {
//构建日志实例
instance = newInstance(name);⬅️
//缓存到实例表
instances.put(name, instance);
}
return instance;
}

//构建日志实例
protected Log newInstance(final String name) throws LogConfigurationException {
Log instance;
//没有日志构造进入,有日志构造直接创建
if (logConstructor == null) {
//发现日志实现
instance = discoverLogImplementation(name);⬅️
}
else {
final Object params[] = { name };
instance = (Log) logConstructor.newInstance(params);
}

if (logMethod != null) {
final Object params[] = { this };
logMethod.invoke(instance, params);
}
return instance;
}

//实现类集
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"
};

//发现日志实现
private Log discoverLogImplementation(final String logCategory) throws LogConfigurationException {
Log result = null;
// ...
for(int i=0; i<classesToDiscover.length && result == null; ++i) {
//从具体日志类中创建日志实例
result = createLogFromClass(classesToDiscover[i], logCategory, true);⬅️
}
//...
return result;
}

//创建日志实例
private Log createLogFromClass(final String logAdapterClassName,
final String logCategory,
final boolean affectState)
throws LogConfigurationException {
Log logAdapter = null;
Constructor constructor = null;
Class logAdapterClass = null;
//获取应用类加载
ClassLoader currentCL = getBaseClassLoader();

for(;;) {
Class c;
try {
//加载实现类
c = Class.forName(logAdapterClassName, true, currentCL);
} catch (final ClassNotFoundException originalClassNotFoundException) {
// ...
}

//获取类构造
constructor = c.getConstructor(logConstructorSignature);
//构建实例
final Object o = constructor.newInstance(params);⬅️

//日志对象验证
if (o instanceof Log) {
logAdapterClass = c;
logAdapter = (Log) o;
break;
}
}
if (logAdapterClass != null && affectState) {
this.logClassName = logAdapterClassName;//日志适配器类名
this.logConstructor = constructor;//日志构造器
try {
this.logMethod = logAdapterClass.getMethod("setLogFactory", logMethodSignature);
} catch (final Throwable t) {
// ...
}
}
return logAdapter;
}
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

请我喝杯咖啡吧~

支付宝
微信