您的位置:首页 > 编程语言 > Java开发

springMVC+log4j源码简单分析

2015-07-31 00:00 761 查看
之前说过使用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的配置文件同样也可以正常的使用的原因了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: