日志组件介绍: http://www.blogjava.net/daiyongzhi/archive/2014/04/13/412364.html
Log4j包使用说明: http://www.360doc.com/content/10/1224/19/573136_81037906.shtml
Log4j配置: http://blog.csdn.net/azheng270/article/details/2173430/
Log4j初始化详解: http://donald-draper.iteye.com/blog/2332385
相关log4j的jar包,配置,使用上面链接已经说明,这里就不做介绍,今天来探究一下,与Spring的集成过程分析:
1.在web.xml配置log4属性文件位置:
log4jConfigLocation classpath*:log4j.properties
2.添加监听器:
org.springframework.web.util.Log4jConfigListener
到这里配置完毕。
下面分析过程:
配置文件加载通过Tomcat-StandardContext
protected synchronized void startInternal() throws LifecycleException { try { // Create context attributes that will be required if (ok) { getServletContext().setAttribute( JarScanner.class.getName(), getJarScanner()); } //此函数初始化Web上下文变量,log4j属性文件位置 // Set up the context init params mergeParameters(); // Call ServletContainerInitializers for (Map.Entry>> entry : initializers.entrySet()) { try { entry.getKey().onStartup(entry.getValue(), getServletContext()); } catch (ServletException e) { log.error(sm.getString("standardContext.sciFail"), e); ok = false; break; } } //添加web监听器 // Configure and call application event listeners if (ok) { if (!listenerStart()) { log.error(sm.getString("standardContext.listenerFail")); ok = false; } } }
上下文变量初始化
private void mergeParameters() { MapmergedParams = new HashMap (); String names[] = findParameters(); for (int i = 0; i < names.length; i++) { mergedParams.put(names[i], findParameter(names[i])); } ApplicationParameter params[] = findApplicationParameters(); for (int i = 0; i < params.length; i++) { if (params[i].getOverride()) { if (mergedParams.get(params[i].getName()) == null) { mergedParams.put(params[i].getName(), params[i].getValue()); } } else { mergedParams.put(params[i].getName(), params[i].getValue()); } } ServletContext sc = getServletContext(); for (Map.Entry entry : mergedParams.entrySet()) { //将上下文变量放在ServletContext中 sc.setInitParameter(entry.getKey(), entry.getValue()); } }
监听器添加
public boolean listenerStart() { ApplicationListener listeners[] = applicationListeners; // Sort listeners in two arrays ArrayList
查看Spring log4j监听器
public class Log4jConfigListener implements ServletContextListener { public Log4jConfigListener() { } public void contextInitialized(ServletContextEvent event) { //初始化log4J位置,通过event.getServletContext()获取 Log4jWebConfigurer.initLogging(event.getServletContext()); } public void contextDestroyed(ServletContextEvent event) { Log4jWebConfigurer.shutdownLogging(event.getServletContext()); } }
log4jWeb初始化Log4jWebConfigurer
public static void initLogging(ServletContext servletContext) { if(exposeWebAppRoot(servletContext)) WebUtils.setWebAppRootSystemProperty(servletContext); String location = servletContext.getInitParameter("log4jConfigLocation"); if(location != null) try { location = ServletContextPropertyUtils.resolvePlaceholders(location, servletContext); if(!ResourceUtils.isUrl(location)) location = WebUtils.getRealPath(servletContext, location); servletContext.log((new StringBuilder()).append("Initializing log4j from [").append(location).append("]").toString()); String intervalString = servletContext.getInitParameter("log4jRefreshInterval"); if(StringUtils.hasText(intervalString)) try { long refreshInterval = Long.parseLong(intervalString); //初始化log4j配置 Log4jConfigurer.initLogging(location, refreshInterval); } catch(NumberFormatException ex) { throw new IllegalArgumentException((new StringBuilder()).append("Invalid 'log4jRefreshInterval' parameter: ").append(ex.getMessage()).toString()); } else Log4jConfigurer.initLogging(location); } catch(FileNotFoundException ex) { throw new IllegalArgumentException((new StringBuilder()).append("Invalid 'log4jConfigLocation' parameter: ").append(ex.getMessage()).toString()); } }
log4j属性变量配置Log4jConfigurer
public static void initLogging(String location, long refreshInterval) throws FileNotFoundException { String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(location); File file = ResourceUtils.getFile(resolvedLocation); if(!file.exists()) throw new FileNotFoundException((new StringBuilder()).append("Log4j config file [").append(resolvedLocation).append("] not found").toString()); //xml文件 if(resolvedLocation.toLowerCase().endsWith(".xml")) DOMConfigurator.configureAndWatch(file.getAbsolutePath(), refreshInterval); else //properties文件 PropertyConfigurator.configureAndWatch(file.getAbsolutePath(), refreshInterval); }
PropertyConfigurator,属性文件读取
public void doConfigure(Properties properties, LoggerRepository hierarchy) { repository = hierarchy; String value = properties.getProperty("log4j.debug"); if(value == null) { value = properties.getProperty("log4j.configDebug"); if(value != null) LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead."); } if(value != null) LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true)); String reset = properties.getProperty("log4j.reset"); if(reset != null && OptionConverter.toBoolean(reset, false)) hierarchy.resetConfiguration(); String thresholdStr = OptionConverter.findAndSubst("log4j.threshold", properties); if(thresholdStr != null) { hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr, Level.ALL)); LogLog.debug("Hierarchy threshold set to [" + hierarchy.getThreshold() + "]."); } //关键是下面三个函数配置LogFactory属性 configureRootCategory(properties, hierarchy); configureLoggerFactory(properties); parseCatsAndRenderers(properties, hierarchy); LogLog.debug("Finished configuring."); registry.clear(); }
至此LogFactory初始化完毕。
Logger实例的获取
public static Logger getLogger(Class clazz) { //根据类名获取logger实例 Logger logger = getLogger(clazz.getName()); if(DETECT_LOGGER_NAME_MISMATCH) { Class autoComputedCallingClass = Util.getCallingClass(); if(nonMatchingClasses(clazz, autoComputedCallingClass)) { Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", new Object[] { logger.getName(), autoComputedCallingClass.getName() })); Util.report("See http://www.slf4j.org/codes.html#loggerNameMismatch for an explanation"); } } return logger; }
public static Logger getLogger(String name) { //从具体的log工场实现中,获取log //slf4j只是提供了一个工场类接口,具体的工场实现类在相关日志Jar包中 ILoggerFactory iLoggerFactory = getILoggerFactory(); return iLoggerFactory.getLogger(name); }
写的有点匆忙,请见谅!