作用
配置工廠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)