Log4J2(六) - 配置工廠ConfigurationFactory的初始化過程-源碼解析

作用

配置工廠ConfigurationFactory是用於加載用戶的配置文件的,配置文件是怎麼獲取的?這篇文章就是講的通過ConfigurationFactory去獲取配置文件的過程。

實例

  • ConfigurationFactory在類初始化的時候, 通過餓漢式模式創建單實例。Factory是其靜態內部子類
private static ConfigurationFactory configFactory = new Factory();

private static class Factory extends ConfigurationFactory {
//省略部分代碼
}
  • ConfigurationFactory通過getInstance方法獲取其實例。

初始化

設計模式

在getInstance方法中進行初始化,雙檢鎖模式保證只被初始化一次

	private static volatile List<ConfigurationFactory> factories = null;
    private static final Lock LOCK = new ReentrantLock();

	public static ConfigurationFactory getInstance() {
        if (factories == null) {
            LOCK.lock();
            try {
            	if (factories == null) {
               		//省略部分代碼以說明雙檢鎖模式
                }
            } finally {
                LOCK.unlock();
            }
        }
        return configFactory;
    }

初始化流程圖

配置工廠類初始化流程

代碼解析

  • 自定義配置工廠類需要設置屬性log4j.configurationFactory即可, 代碼如下:
	final String factoryClass = PropertiesUtil.getProperties().getStringProperty(CONFIGURATION_FACTORY_PROPERTY);
    if (factoryClass != null) {
        addFactory(list, factoryClass);
    }
  • 獲取內置配置工廠類並加入配置工廠列表
	//獲取插件
	//CATEGORY的值爲ConfiguratioFactory
	final PluginManager manager = new PluginManager(CATEGORY);
    manager.collectPlugins();
    final Map<String, PluginType<?>> plugins = manager.getPlugins();
    
    //對內置加載的類進行類型檢查並加入到未排序列表
    final List<Class<? extends ConfigurationFactory>> ordered = new ArrayList<>(plugins.size());
    for (final PluginType<?> type : plugins.values()) {
        try {
            ordered.add(type.getPluginClass().asSubclass(ConfigurationFactory.class));
        } catch (final Exception ex) {
            LOGGER.warn("Unable to add class {}", type.getPluginClass(), ex);
        }
    }
    
    //按照OrderComparator定義的順序進行加載
    Collections.sort(ordered, OrderComparator.getInstance());
    for (final Class<? extends ConfigurationFactory> clazz : ordered) {
        addFactory(list, clazz);
    }
    //轉變成unmodified的list
    factories = Collections.unmodifiableList(list);
  • PluginManager收集插件的方法解析
    內置配置工廠類加載流程
    說明:

    • 如果不瞭解OSGI可以看看這篇文章
    • ConfigurationFactory初始化過程中,packages被指定爲null
  • OrdeComparator,優先級比較器

 public int compare(final Class<?> lhs, final Class<?> rhs) {
        final Order lhsOrder = Objects.requireNonNull(lhs, "lhs").getAnnotation(Order.class);
        final Order rhsOrder = Objects.requireNonNull(rhs, "rhs").getAnnotation(Order.class);
        if (lhsOrder == null && rhsOrder == null) {
            return 0;
        }
        //有@Order註解的優先級高
        if (rhsOrder == null) {
            return -1;
        }
        //有@Order註解的優先級高
        if (lhsOrder == null) {
            return 1;
        }
        //@Order註解的值越大,優先級越高
        return Integer.signum(rhsOrder.value() - lhsOrder.value());
    }

舉個例子:
JsonConfigurationFacotory的Order值是6,YamlConfigurationFactory的Order值是7,那麼YamlConfigurationFactory應該排在JsonConfigurationFacotory之前。內置一共四個解析插件,他們的排序是:
* PropertiesConfigurationFactory (8)
* YamlConfigurationFactory (7)
* JsonConfigurationFacotory (6)
* XmlConfigurationFactory (5)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章