文档章节

springMVC+log4j源码简单分析

有理想的鸭子
 有理想的鸭子
发布于 2015/07/31 17:53
字数 777
阅读 23
收藏 1

之前说过使用Spring做web项目时,及时不在web.xml中定义log4j.xml的路径,在实际仍可以正确运行,下面将根据源码来简单分析一下:

1.web.xml配置如下:

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>maven</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>maven</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

 2.将log4j.xml文件放在web-inf/classes下:

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	<!-- Appenders -->
	
	<appender name="files" class="org.apache.log4j.DailyRollingFileAppender">
		<param name="File" value="${catalina.base}/logs/mytest.log"/>
		<param name="DatePattern" value="'.'yyyy-MM-dd'.log'"/>
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss SSS\} %-5p] [%t] %c{3\} - %m%n"/>
		</layout>
	</appender>
	
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss SSSS\} %-5p] [%t] %c{3\} - %m%n" />
		</layout>
	</appender>
	
	<!-- Application Loggers -->
	<logger name="org.springframework.samples.mvc">
		<level value="info" />
		<appender-ref ref="files"/>
	</logger>
	
	<logger name="com.zxhz.maventest">
		<level value="info" />
		<appender-ref ref="files"/>
	</logger>
	
	<!-- 3rdparty Loggers -->
	<logger name="org.springframework.core">
		<level value="info" />
		<appender-ref ref="files"/>
	</logger>
	
	<logger name="org.springframework.beans">
		<level value="info" />
		<appender-ref ref="files"/>
	</logger>
	
	<logger name="org.springframework.context">
		<level value="info" />
		<appender-ref ref="files"/>
	</logger>

	<logger name="org.springframework.http">
		<level value="debug" />
		<appender-ref ref="files"/>
	</logger>

	<logger name="org.springframework.web">
		<level value="debug" />
		<appender-ref ref="files"/>
	</logger>

	<!-- Root Logger -->
	<root>
		<priority value="warn" />
		<appender-ref ref="console" />
	</root>
	
</log4j:configuration>

 3.开始分析过程:

 

  当启动Tomcat的时候,Tomcat会读取web.xml配置文件,根据配置文件加载数据从web.xml文件中我们可以看到Tomcat会先加载

 

<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

 这个<listener>将会被先运行。再ContextLoaderListener.java这个类里我们可以看到:

package org.springframework.web.context;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {

	private ContextLoader contextLoader;


	/**
	 * Initialize the root web application context.
	 */
	public void contextInitialized(ServletContextEvent event) {
		this.contextLoader = createContextLoader();
		if (this.contextLoader == null) {
			this.contextLoader = this;
		}
		this.contextLoader.initWebApplicationContext(event.getServletContext());
	}

	//......

}

 首先这里会先运行contextInitialized()对其进行初始化操作并且会调用contextLoader的initWebApplicationContext方法并且在initWebApplicationContext方法中会创建一个logger

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
			throw new IllegalStateException(
					"Cannot initialize context because there is already a root application context present - " +
					"check whether you have multiple ContextLoader* definitions in your web.xml!");
		}

		Log logger = LogFactory.getLog(ContextLoader.class);//初始化log
		servletContext.log("Initializing Spring root WebApplicationContext");
		if (logger.isInfoEnabled()) {
			logger.info("Root WebApplicationContext: initialization started");
		}
		long startTime = System.currentTimeMillis();

		try {
//........略1000字。。。。

 当执行

Log logger = LogFactory.getLog(ContextLoader.class);

 的时候会去调用会去找到LogFactory.getLog方法最终这个方法会通过LogManager类中的静态代码块去调用到Log4j中的Loader.class中的方法完成Log4j的初始化:

static {
      /***
       *  ..........
       */
      // 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.");
        try {
            OptionConverter.selectAndConfigure(url, configuratorClassName,
					   LogManager.getLoggerRepository());
        } catch (NoClassDefFoundError e) {
            LogLog.warn("Error during default initialization", e);
        }
      } else {
	    LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
      }
    } else {
        LogLog.debug("Default initialization of overridden by " + 
            DEFAULT_INIT_OVERRIDE_KEY + "property."); 
    }  
  }

 Loader.getResource

static public URL getResource(String resource) {
    ClassLoader classLoader = null;
    URL url = null;
    
    try {
  	if(!java1 && !ignoreTCL) {
  	  classLoader = getTCL();
  	  if(classLoader != null) {
  	    LogLog.debug("Trying to find ["+resource+"] using context classloader "
  			 +classLoader+".");
  	    url = classLoader.getResource(resource);      
  	    if(url != null) {
  	      return url;
  	    }
  	  }
  	}

 这就是为什么我们不在web.xml中定义log4j.xml的配置文件同样也可以正常的使用的原因了

 

© 著作权归作者所有

共有 人打赏支持
有理想的鸭子
粉丝 3
博文 47
码字总数 20092
作品 0
武汉
高级程序员
私信 提问
Spring IOC 容器源码分析 - 填充属性到 bean 原始对象

1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的。我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反射创建一个原始的 ...

coolblog.xyz
2018/06/11
0
0
Spring AOP 源码分析 - 筛选合适的通知器

1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析。本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出合适的通知器(Advisor...

java高级架构牛人
2018/06/21
0
0
Android进阶——源码分析之图片加载框架Glide

前言 源码阅读不是一件简单的事情,每次都要花费很长时间来梳理其内部的原理,所以有朋友觉得看一遍看不懂,那很正常,接下来就是考验你耐心的时候。学习源码的目的是:学习它好的地方,吸收...

qq_30379689
2017/10/15
0
0
Spring MVC 原理探秘 - 容器的创建过程

1.简介 在上一篇文章中,我向大家介绍了 Spring MVC 是如何处理 HTTP 请求的。Spring MVC 可对外提供服务时,说明其已经处于了就绪状态。再次之前,Spring MVC 需要进行一系列的初始化操作。...

coolblog.xyz
2018/07/03
0
0
struts2源码分析之配置文件加载顺序

本次源码分析的目标: 弄清struts2加载各配置文件的顺序,得到此配置文件加载顺序,则源码分析任务结束。 引言 问题的引出是由于前些天在oschina上看到的一篇帖子,http://www.oschina.net/...

算法与编程之美
2013/04/09
0
6

没有更多内容

加载失败,请刷新页面

加载更多

租房软件隐私保护如同虚设

近日,苏州市民赵先生向江苏新闻广播新闻热线025-84658888反映,他在“安居客”手机应用软件上浏览二手房信息,并且使用该软件自动生成的虚拟号码向当地一家中介公司进行咨询。可电话刚挂不久...

linux-tao
今天
1
0
分布式项目(五)iot-pgsql

书接上回,在Mapping server中,我们已经把数据都整理好了,现在利用postgresql存储历史数据。 iot-pgsql 构建iot-pgsql模块,这里我们写数据库为了性能考虑不在使用mybatis,换成spring jd...

lelinked
今天
4
0
一文分析java基础面试题中易出错考点

前言 这篇文章主要针对的是笔试题中出现的通过查看代码执行结果选择正确答案题材。 正式进入题目内容: 1、(单选题)下面代码的输出结果是什么? public class Base { private Strin...

一看就喷亏的小猿
今天
2
0
cocoapods 用法

cocoapods install pod install 更新本地已经install的仓库 更新所有的仓库 pod update --verbose --no-repo-update 更新制定的仓库 pod update ** --verbose --no-repo-update...

HOrange
今天
3
0
linux下socket编程实现一个服务器连接多个客户端

使用socekt通信一般步骤 1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。 2)客户端:socker()建立套接字,连接(connect)服务器,连接上后...

shzwork
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部