LogManager启动主要类
LogManager
LoggerContextFactory
LogManager启动入口是以下static代码
static {
//绑定一个LoggerContextFactory,获取配置文件
//private static final PropertiesUtil LOG4J_PROPERTIES = new PropertiesUtil("log4j2.component.properties");
//中的属性【log4j2.loggerContextFactory】
final PropertiesUtil managerProps = PropertiesUtil.getProperties();
final String factoryClassName = managerProps.getStringProperty(FACTORY_PROPERTY_NAME);
if (factoryClassName != null) {
try {
//
factory = LoaderUtil.newCheckedInstanceOf(factoryClassName, LoggerContextFactory.class);
} catch (final ClassNotFoundException cnfe) {
LOGGER.error("Unable to locate configured LoggerContextFactory {}", factoryClassName);
} catch (final Exception ex) {
LOGGER.error("Unable to create configured LoggerContextFactory {}", factoryClassName, ex);
}
}
if (factory == null) {
final SortedMap<Integer, LoggerContextFactory> factories = new TreeMap<>();
// note that the following initial call to ProviderUtil may block until a Provider has been installed when
// running in an OSGi environment
/*
通过provider实例化LoggerContextFactory对象
log4j2是通过META-INF中的log4j-provider.properties文件获取具体的LoggerContextFactory
file:/user/home/.m2/repository/org/apache/logging/log4j/log4j-core/2.8.2/log4j-core-2.8.2.jar!/META-INF/log4j-provider.properties
LoggerContextFactory = org.apache.logging.log4j.core.impl.Log4jContextFactory
Log4jAPIVersion = 2.6.0
FactoryPriority= 10
因此默认的 LoggerContextFactory是Log4jContextFactory
*/
if (ProviderUtil.hasProviders()) {
for (final Provider provider : ProviderUtil.getProviders()) {
final Class<? extends LoggerContextFactory> factoryClass = provider.loadLoggerContextFactory();
if (factoryClass != null) {
try {
factories.put(provider.getPriority(), factoryClass.newInstance());
} catch (final Exception e) {
LOGGER.error("Unable to create class {} specified in {}", factoryClass.getName(), provider
.getUrl().toString(), e);
}
}
}
if (factories.isEmpty()) {
LOGGER.error("Log4j2 could not find a logging implementation. "
+ "Please add log4j-core to the classpath. Using SimpleLogger to log to the console...");
factory = new SimpleLoggerContextFactory();
} else if (factories.size() == 1) {
factory = factories.get(factories.lastKey());
} else {
final StringBuilder sb = new StringBuilder("Multiple logging implementations found: \n");
for (final Map.Entry<Integer, LoggerContextFactory> entry : factories.entrySet()) {
sb.append("Factory: ").append(entry.getValue().getClass().getName());
sb.append(", Weighting: ").append(entry.getKey()).append('\n');
}
factory = factories.get(factories.lastKey());
sb.append("Using factory: ").append(factory.getClass().getName());
LOGGER.warn(sb.toString());
}
} else {
LOGGER.error("Log4j2 could not find a logging implementation. "
+ "Please add log4j-core to the classpath. Using SimpleLogger to log to the console...");
factory = new SimpleLoggerContextFactory();
}
}
}
配置文件解析
public static ConfigurationFactory getInstance() {
// volatile works in Java 1.6+, so double-checked locking also works properly
//noinspection DoubleCheckedLocking
if (factories == null) {
LOCK.lock();
try {
if (factories == null) {
final List<ConfigurationFactory> list = new ArrayList<>();
//CONFIGURATION_FACTORY_PROPERTY = "log4j.configurationFactory";
final String factoryClass = PropertiesUtil.getProperties().getStringProperty(CONFIGURATION_FACTORY_PROPERTY);
if (factoryClass != null) {
addFactory(list, factoryClass);
}
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);
}
}
Collections.sort(ordered, OrderComparator.getInstance());
for (final Class<? extends ConfigurationFactory> clazz : ordered) {
addFactory(list, clazz);
}
// see above comments about double-checked locking
//noinspection NonThreadSafeLazyInitialization
factories = Collections.unmodifiableList(list);
}
} finally {
LOCK.unlock();
}
}
LOGGER.debug("Using configurationFactory {}", configFactory);
return configFactory;
}
public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
if (configLocation == null) {
/*
//CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile";
1、log4j.configurationFile---ConfigurationFactory
*/
final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties()
.getStringProperty(CONFIGURATION_FILE_PROPERTY));
if (configLocationStr != null) {
final String[] sources = configLocationStr.split(",");
if (sources.length > 1) {
final List<AbstractConfiguration> configs = new ArrayList<>();
for (final String sourceLocation : sources) {
final Configuration config = getConfiguration(loggerContext, sourceLocation.trim());
if (config != null && config instanceof AbstractConfiguration) {
configs.add((AbstractConfiguration) config);
} else {
LOGGER.error("Failed to created configuration at {}", sourceLocation);
return null;
}
}
return new CompositeConfiguration(configs);
}
return getConfiguration(loggerContext, configLocationStr);
}
/*
2、log4j2-test.properties---PropertiesConfigurationFactory
3、log4j2-test.yaml/log4j2-test.yml---YAMLConfigurationFactory
4、log4j2-test.json/log4j2-test.jsn---JsonConfigurationFactory
5、log4j2-test.xml---XMLConfigurationFactory
6、log4j2.properties---PropertiesConfigurationFactory
7、log4j2.yaml/log4j2.yml---YAMLConfigurationFactory
8、log4j2.json/log4j2.jsn---JSONConfigurationFactory
9、log4j2.xml---XMLConfigurationFactory
10、console控制台---DefaultConfiguration
*/
for (final ConfigurationFactory factory : getFactories()) {
final String[] types = factory.getSupportedTypes();
if (types != null) {
for (final String type : types) {
if (type.equals(ALL_TYPES)) {
final Configuration config = factory.getConfiguration(loggerContext, name, configLocation);
if (config != null) {
return config;
}
}
}
}
}
} else {
// configLocation != null
final String configLocationStr = configLocation.toString();
for (final ConfigurationFactory factory : getFactories()) {
final String[] types = factory.getSupportedTypes();
if (types != null) {
for (final String type : types) {
if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) {
final Configuration config = factory.getConfiguration(loggerContext, name, configLocation);
if (config != null) {
return config;
}
}
}
}
}
}
Configuration config = getConfiguration(loggerContext, true, name);
if (config == null) {
config = getConfiguration(loggerContext, true, null);
if (config == null) {
config = getConfiguration(loggerContext, false, name);
if (config == null) {
config = getConfiguration(loggerContext, false, null);
}
}
}
if (config != null) {
return config;
}
LOGGER.error("No Log4j 2 configuration file found. " +
"Using default configuration (logging only errors to the console), " +
"or user programmatically provided configurations. " +
"Set system property 'log4j2.debug' " +
"to show Log4j 2 internal initialization logging. " +
"See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2");
return new DefaultConfiguration();
}