沒有讀過源碼童鞋第一眼看到這個類肯定是一臉懵逼的,加上網上分析這個的類的文章基本上沒有,心中更生疑惑。
創建的時機
NullConfiguration是LoggerContext的一個靜態變量,在執行LoggerContext的構造方法之前執行:
private static final Configuration NULL_CONFIGURATION = new NullConfiguration();
用在哪兒?
在LoggerContext執行stop方法時,用於替代當前的配置文件,然後執行Log4J的收尾工作。
這樣做的好處是可以避免在收尾工作的時候,還有應用程序打印日誌而報錯。關鍵部分代碼如下:
final Configuration prev = configuration;
configuration = NULL_CONFIGURATION;
updateLoggers();
//兩種不同的收尾方式:超時和不帶超時的方式
if (prev instanceof LifeCycle2) {
((LifeCycle2) prev).stop(timeout, timeUnit);
} else {
prev.stop();
}
內部構造
- NullConfiguration的代碼如下:
public class NullConfiguration extends AbstractConfiguration {
/**
* Name of this configuration.
*/
public static final String NULL_NAME = "Null";
public NullConfiguration() {
//執行AbstractionConfiguration的構造方法
super(null, ConfigurationSource.NULL_SOURCE);
//設置配置的名字
setName(NULL_NAME);
//獲取root logger, 這個rootLogger是在AbstractionConfiguration創建的,稍微分析
final LoggerConfig root = getRootLogger();
//日誌等級設置爲關閉, 也就是說不會有任何的日誌打印了
root.setLevel(Level.OFF);
}
}
- 來看看父類的構造方法
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);
}
小結
NullConfiguration正如其名,本身就是個空殼兒的配置,作用是爲了避免在配置收尾工作的時候發生不必要的錯誤調用。