`
Donald_Draper
  • 浏览: 981000 次
社区版块
存档分类
最新评论

Spring集成log4j,日志初始化过程详解

阅读更多
以前研究过slf4j-log4j的使用,但具体初始化过程不是很清楚,今天闲下来,翻了一下源码,一探究竟。
日志组件介绍: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属性文件位置:
      
 <context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>classpath*:log4j.properties</param-value>
	</context-param>

2.添加监听器:
<listener>
     <listener-class>
           org.springframework.web.util.Log4jConfigListener
     </listener-class>
</listener>

到这里配置完毕。
下面分析过程:
配置文件加载通过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<ServletContainerInitializer, Set<Class<?>>> 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() {
        Map<String,String> mergedParams = new HashMap<String,String>();
        
        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<String,String> entry : mergedParams.entrySet()) {
            //将上下文变量放在ServletContext中
            sc.setInitParameter(entry.getKey(), entry.getValue());
        }

    }

监听器添加
 public boolean listenerStart() {
        ApplicationListener listeners[] = applicationListeners;

        // Sort listeners in two arrays
        ArrayList<Object> eventListeners = new ArrayList<Object>();
        ArrayList<Object> lifecycleListeners = new ArrayList<Object>();
        for (int i = 0; i < results.length; i++) {
            if ((results[i] instanceof ServletContextAttributeListener)
                || (results[i] instanceof ServletRequestAttributeListener)
                || (results[i] instanceof ServletRequestListener)
                || (results[i] instanceof HttpSessionAttributeListener)) {
                eventListeners.add(results[i]);
            }
            if ((results[i] instanceof ServletContextListener)
                || (results[i] instanceof HttpSessionListener)) {
                lifecycleListeners.add(results[i]);
            }
        }

        // Listener instances may have been added directly to this Context by
        // ServletContextInitializers and other code via the pluggability APIs.
        // Put them these listeners after the ones defined in web.xml and/or
        // annotations then overwrite the list of instances with the new, full
        // list.
        for (Object eventListener: getApplicationEventListeners()) {
            eventListeners.add(eventListener);
        }
        setApplicationEventListeners(eventListeners.toArray());
        for (Object lifecycleListener: getApplicationLifecycleListeners()) {
            //添加监听器
            lifecycleListeners.add(lifecycleListener);
            if (lifecycleListener instanceof ServletContextListener) {
                noPluggabilityListeners.add(lifecycleListener);
            }
        }
        setApplicationLifecycleListeners(lifecycleListeners.toArray());

        // Send application start events

        if (getLogger().isDebugEnabled())
            getLogger().debug("Sending application start events");

        // Ensure context is not null
        getServletContext();
        context.setNewServletContextListenerAllowed(false);
        
        Object instances[] = getApplicationLifecycleListeners();
        if (instances == null || instances.length == 0) {
            return ok;
        }

        ServletContextEvent event = new ServletContextEvent(getServletContext());
        ServletContextEvent tldEvent = null;
        if (noPluggabilityListeners.size() > 0) {
            noPluggabilityServletContext = new NoPluggabilityServletContext(getServletContext());
            tldEvent = new ServletContextEvent(noPluggabilityServletContext);
        }
        for (int i = 0; i < instances.length; i++) {
            if (instances[i] == null)
                continue;
            if (!(instances[i] instanceof ServletContextListener))
                continue;
            ServletContextListener listener =
                (ServletContextListener) instances[i];
            try {
                fireContainerEvent("beforeContextInitialized", listener);

                if (noPluggabilityListeners.contains(listener)) {
                    listener.contextInitialized(tldEvent);
                } else {
                    listener.contextInitialized(event);
                }
                fireContainerEvent("afterContextInitialized", listener);
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                fireContainerEvent("afterContextInitialized", listener);
                getLogger().error
                    (sm.getString("standardContext.listenerStart",
                                  instances[i].getClass().getName()), t);
                ok = false;
            }
        }

查看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);
    }

写的有点匆忙,请见谅!
分享到:
评论

相关推荐

    spring-boot-starter-log4j2

    当我们添加这个依赖到项目中,Spring Boot会自动配置Log4j2,无需手动进行繁琐的初始化设置。 三、集成步骤 1. 添加依赖:在Maven或Gradle的配置文件中引入"spring-boot-starter-log4j2"依赖,如下所示(以Maven为...

    Spring对Log4J的增强.txt

    - **作用**:监听器类,用于初始化和刷新Log4J配置。 - **示例**: ```xml &lt;listener-class&gt;org.springframework.web.util.Log4jConfigListener ``` - **说明**:通过注册`Log4jConfigListener`监听器,...

    SpringBoot整合log4j

    Spring Boot作为一款简化Spring应用初始搭建以及开发过程的框架,提供了对多种日志系统的支持,其中就包括Log4j。本文将详细介绍如何在Spring Boot项目中整合Log4j,实现灵活的日志管理。 1. **Log4j介绍** Log4j...

    log4j-1.2.15.jar

    Log4j与Spring、Hibernate等众多Java框架有良好的集成,使得开发者可以在这些框架的基础上轻松实现日志记录。 总结来说,log4j-1.2.15.jar是一个功能强大、灵活的日志框架,它在旧项目中的持久存在证明了其价值。...

    搭建struts hibernate log4j spring(好东西)

    ### 搭建Struts、Hibernate、Log4j与Spring集成环境详解 #### 一、简介 本文将详细介绍如何在Web项目中集成Struts、Hibernate、Log4j以及Spring框架,构建一个完整的Java Web应用程序环境。这些技术组合在一起能够...

    log4j各种配置连接

    在Spring应用中,可以通过配置`log4jConfigurer` bean来加载log4j配置,确保在Spring启动时正确初始化日志系统。 六、日志性能优化 1. 日志级别选择:根据实际需求调整日志级别,避免大量无用的日志输出。 2. 文件...

    Spring集成ActiveMQ配置

    此外,还需要引入JMS规范的实现包`jms-1.1.jar`,以及其他日志相关的库,如`log4j-1.2.15.jar`和`slf4j`系列的库。 ### 集成步骤 集成的关键在于Spring配置文件的编写。配置文件应遵循Spring的XML命名空间和schema...

    sturts2+spring2.5+hibernate3.5+c3p0+log4j整合示例项目

    ### Log4j日志系统 Log4j是Apache的一个开源项目,用于记录程序运行时的日志信息。它提供了灵活的日志级别和多种输出方式,如控制台、文件、邮件等,方便开发者调试和追踪问题。在本项目中,Log4j被配置用于记录...

    Spring Boot详解

    - 支持各种日志框架,如Logback、Log4j2等,通过logging.level属性配置日志级别。 - 自动配置日志输出格式和位置。 10. 缓存支持与配置详解 - 支持多种缓存技术,如Redis、Hazelcast、Infinispan等。 - 使用@...

    毕业设计资料管理系统-springboot整合ssm,shiro,log4j.zip

    【标题】:“毕业设计资料管理系统”是基于SpringBoot框架,并且集成了SSM(Spring、SpringMVC、MyBatis)三大核心组件,同时引入了Shiro安全框架以及Log4j日志管理工具。这样的系统设计旨在提供一个高效、安全的...

    Spring入门十大问题

    #### 二、Spring配置问题:Log4j初始化警告 **知识点:** - **Log4j初始化警告**:“Please initialize the log4j system properly”通常是因为log4j.properties文件未正确配置或缺失。 - **解决方案**: - 确保...

    ssi2整合步骤

    尽管具体的图片内容未给出,但根据上下文推测这些库文件可能包含了Spring框架、Log4j日志记录工具、Struts2框架等相关依赖。因此,在搭建SSI2整合项目时,首先需要明确项目依赖的库文件。 #### Spring框架 - **...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    8.4.3 改变初始化和销毁方式 8.4.4 改变异常处理的方式 8.5 小结 第九章 CVS使用指南 9.1 CVS介绍 9.1.1 CVS简介 9.1.2 为什么要使用CVS 9.2 建立CVS的开发环境 9.2.1 下载CVS 9.2.2 配置CVS 9.3 CVS的使用方法 ...

    学习spring的好东西

    **六、Log4j日志记录** Log4j是Java中的常用日志记录工具,Spring框架可以与Log4j结合使用,方便记录应用运行时的日志信息,帮助调试和追踪错误。 **七、Spring注解配置** Spring的注解配置使得开发更加简洁,通过@...

    Struts2_Spring_Hibernate集成

    - **日志配置**: 配置log4j或slf4j等日志框架,记录系统运行状态。 - **性能优化**: 考虑到性能问题,合理配置缓存策略,比如使用二级缓存等。 通过上述步骤,我们可以成功地将Struts2、Spring与Hibernate三个框架...

    spring-4.3.1 jar包

    它提供了一个统一的日志接口,使得开发者可以方便地更换底层的日志实现,如log4j或java.util.logging。 总结来说,Spring 4.3.1版本的这些jar包共同构建了Spring框架的核心功能,包括依赖注入、面向切面编程、上...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    8.4.3 改变初始化和销毁方式 8.4.4 改变异常处理的方式 8.5 小结 第九章 CVS使用指南 9.1 CVS介绍 9.1.1 CVS简介 9.1.2 为什么要使用CVS 9.2 建立CVS的开发环境 9.2.1 下载CVS 9.2.2 配置CVS 9.3 CVS的使用方法 ...

    spring4 api

    - **使用Log4J**:对于已经使用Log4J的项目,可以直接集成使用。 #### 二、Spring Framework 4.x 的新特性 1. **改善的入门体验** - Spring 4.x提供了一个更友好的入门指南和示例代码。 2. **移除过时的包和...

    Spring配置总结

    这是因为Spring应用通常需要日志记录功能,而Log4j是常用的日志库之一。为了防止在同一容器中部署多个应用时的日志配置冲突,我们需要通过设置唯一的`webAppRootKey`来指定日志的存储路径。如下面的代码所示: ```...

Global site tag (gtag.js) - Google Analytics