Log4J2(六) - 配置工厂ConfigurationFactory的初始化过程-源码解析

x33g5p2x  于2021-12-25 转载在 其他  
字(2.5k)|赞(0)|评价(0)|浏览(378)

作用

配置工厂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)

相关文章