之前分析过Log4J2是怎么加载我们应用程序中的配置文件的,参见Log4J2(五) - 配置文件是怎么获取的? . 但是当我们没有配置文件的时候,你会发现控制台会打印错误,这个时候你有没有想过一个问题:为什么没有配置好日志系统,它也能打印日志呢?
因为它在加载自定义的配置之前新建了一套默认配置。
ps:这里说的打印日志是指的应用程序打印日志,不是只Log4J2本身的日志,它本身的日志是由StatusLogger打印的,这个后续有时间再分析。
创建时机
跟NullConguration一样, 是在LoggerContext的构造方法执行之前创建的。
private volatile Configuration configuration = new DefaultConfiguration();
使用时机
当所有的配置方式都没有找到配置时,就会使用默认配置。
代码分析
- 构造方法
public DefaultConfiguration() {
//调用父类AbstractConfiguration的构造方法
super(null, ConfigurationSource.NULL_SOURCE);
//调用父类AbstractConfiguration的setToDefault方法,给rootLogger做默认配置
setToDefault();
}
- 来看看父类的构造方法
private final ConcurrentMap<String, String> properties = new ConcurrentHashMap<>();
// 这就是上面提到的rootLogger,其实就是个空壳
private LoggerConfig root = new LoggerConfig();
protected AbstractConfiguration(final LoggerContext loggerContext, final ConfigurationSource configurationSource) {
//保存loggerContext的一个弱引用
this.loggerContext = new WeakReference<>(loggerContext);
this.configurationSource = Objects.requireNonNull(configurationSource, "configurationSource is null");
//如上面的代码,初始存放的是一个空map
componentMap.put(Configuration.CONTEXT_PROPERTIES, properties);
//新建一个插件管理器
pluginManager = new PluginManager(Node.CATEGORY);
//创建一个空的根节点
rootNode = new Node();
//设置配置状态开启初始化
setState(State.INITIALIZING);
}
- AbstractConfiguration 的setToDefault方法, 也就是默认配置的具体创建过程
protected void setToDefault() {
// LOG4J2-1176 facilitate memory leak investigation
setName(DefaultConfiguration.DEFAULT_NAME + "@" + Integer.toHexString(hashCode()));
//初始化输出的消息样式
//默认格式:%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
final Layout<? extends Serializable> layout = PatternLayout.newBuilder()
.