欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Log4J源码分析(三)

程序员文章站 2022-07-05 09:47:05
...
转载:http://jmut.bokee.com/

上回说到LogManager,接下来就分析它。
先看它的注释:

/**
* Use the LogManager class to retreive {@link Logger}
* instances or to operate on the current {@link
* LoggerRepository}. When the LogManager class is loaded
* into memory the default initalzation procedure is inititated. The
* default intialization procedure is described in the
* href="../../../../manual.html#defaultInit">short log4j manual.
*
* @author Ceki Gülcü */
可见这个类可能是负责全局Logger管理。这个类不大,但感觉它是很重要的一个类,所以有必要深入研究一下。既然在注释中提到了手册中有关于默认初始化过程的描述,那就先看看它是怎么说的。
The exact default initialization algorithm is defined as follows:

Setting the log4j.defaultInitOverride system property to any other value then "false" will cause log4j to skip the default initialization procedure (this procedure).
Set the resource string variable to the value of the log4j.configuration system property. The preferred way to specify the default initialization file is through the log4j.configuration system property. In case the system property log4j.configuration is not defined, then set the string variable resource to its default value "log4j.properties".
Attempt to convert the resource variable to a URL.
If the resource variable cannot be converted to a URL, for example due to a MalformedURLException, then search for the resource from the classpath by calling org.apache.log4j.helpers.Loader.getResource(resource, Logger.class) which returns a URL. Note that the string "log4j.properties" constitutes a malformed URL.
See

Loader.getResource(java.lang.String) for the list of searched locations.
If no URL could not be found, abort default initialization. Otherwise, configure log4j from the URL.
The PropertyConfigurator will be used to parse the URL to configure log4j unless the URL ends with the ".xml" extension, in which case the DOMConfigurator will be used. You can optionaly specify a custom configurator. The value of the log4j.configuratorClass system property is taken as the fully qualified class name of your custom configurator. The custom configurator you specify must implement the Configurator interface.

以上是就是整个初始化过程。其源码如下:
static {
// By default we use a DefaultRepositorySelector which always returns 'h'.
Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
repositorySelector = new DefaultRepositorySelector(h);

/** Search for the properties file log4j.properties in the CLASSPATH. */
String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
null);

// if there is no default init override, then get the resource
// specified by the user or the default config file.
if(override == null || "false".equalsIgnoreCase(override)) {

String configurationOptionStr = OptionConverter.getSystemProperty(
DEFAULT_CONFIGURATION_KEY,
null);

String configuratorClassName = OptionConverter.getSystemProperty(
CONFIGURATOR_CLASS_KEY,
null);

URL url = null;

// if the user has not specified the log4j.configuration
// property, we search first for the file "log4j.xml" and then
// "log4j.properties"
if(configurationOptionStr == null) {
url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
if(url == null) {
url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
}
} else {
try {
url = new URL(configurationOptionStr);
} catch (MalformedURLException ex) {
// so, resource is not a URL:
// attempt to get the resource from the class path
url = Loader.getResource(configurationOptionStr);
}
}

// If we have a non-null url, then delegate the rest of the
// configuration to the OptionConverter.selectAndConfigure
// method.
if(url != null) {
LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
OptionConverter.selectAndConfigure(url, configuratorClassName,
LogManager.getLoggerRepository());
} else {
LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
}
}
1、检查log4j.defaultInitOverride系统变量的值,false将跳过默认初始化过程。

2、读取log4j.configuration系统变量的值,生成配置文件url,默认值为log4j.properties或者log4j.xml。
// if the user has not specified the log4j.configuration
// property, we search first for the file "log4j.xml" and then
// "log4j.properties"
if(configurationOptionStr == null) {
 url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
 if(url == null) {
 url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
 }
} else {
 try {
  url = new URL(configurationOptionStr);
 } catch (MalformedURLException ex) {
 // so, resource is not a URL:
 // attempt to get the resource from the class path
 url = Loader.getResource(configurationOptionStr);
 }
}
3、如果url存在,则继续用OptionConverter初始化。
// If we have a non-null url, then delegate the rest of the
// configuration to the OptionConverter.selectAndConfigure
// method.
if(url != null) {
 LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
 OptionConverter.selectAndConfigure(url, configuratorClassName,
 LogManager.getLoggerRepository());
} else {
 LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
}
我们又发现了三个重要角色 Hierarchy、OptionConverter和Loader。我们先说OptionConverter,显然它是一个工具类,提供一些基础服务。我们现在用到的方法是:
/**
Configure log4j given a URL.
The url must point to a file or resource which will be interpreted by
a new instance of a log4j configurator.
All configurations steps are taken on the hierarchy passed as a parameter.

@param url The location of the configuration file or resource.
@param clazz The classname, of the log4j configurator which will parse
the file or resource at url. This must be a subclass of
{@link Configurator}, or null. If this value is null then a default
configurator of {@link PropertyConfigurator} is used, unless the
filename pointed to by url ends in '.xml', in which case
{@link org.apache.log4j.xml.DOMConfigurator} is used.
@param hierarchy The {@link org.apache.log4j.Hierarchy} to act on.

@since 1.1.4 */

static
public
void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) {
 Configurator configurator = null;
 String filename = url.getFile();

 if(clazz == null && filename != null && filename.endsWith(".xml")) {
  clazz = "org.apache.log4j.xml.DOMConfigurator";
 }

 if(clazz != null) {
  LogLog.debug("Preferred configurator class: " + clazz);
  configurator = (Configurator) instantiateByClassName(clazz,
  Configurator.class,null);
  if(configurator == null) {
   LogLog.error("Could not instantiate configurator ["+clazz+"].");
   return;
  }
 } else {
  configurator = new PropertyConfigurator();
 }

 configurator.doConfigure(url, hierarchy);
}
该方法先构造正确的Configurator,再进行配置。有两个默认的Configurator,一个是DOMConfigurator,一个是PropertyConfigurator是。在没有指定Configurator时,如果配置文件是以.xml结尾,则使用DOMConfigurator,否则使用PropertyConfigurator。