從springmvc啟動日志學習


javaee標准中,tomcat等web容器啟動時走web.xml 先將各種contex-param 放到servletcontxt中變成parameter,然后開始啟動容器,容器對外提供了listener可在容器onstartup時做一些操作。

 

log:

 

二月 25, 2017 2:56:16 下午 org.apache.catalina.core.ApplicationContext log

信息: No Spring WebApplicationInitializer types detected on classpath

 

解釋:---沒找到自定義的spring WebApplicationInitializer

這句日志來自於: org.springframework.web.SpringServletContainerInitializer 在spring-web-x.x.x.Release.jar 包中。

該類實現了servletContainerInitializer 接口的onStartup方法。此接口只有一個方法。這是spring3.1之后的新特性,無web.xml 而是基於代碼注解的配置啟動servlet。引入了servlet3.0.

 

 * @param c the Set of application classes that extend, implement, or

 * have been annotated with the class types specified by the 

 * {@link javax.servlet.annotation.HandlesTypes HandlesTypes} annotation,

 * or <tt>null</tt> if there are no matches, or this

 * <tt>ServletContainerInitializer</tt> has not been annotated with

 * <tt>HandlesTypes</tt>

c這個param比較有意思,需要實現類增加@HandlesTypes(xx.class)注解。如spring的實現類聲明了注解

@HandlesTypes(WebApplicationInitializer.class) 所以spring基於java代碼的配置是需要實現WebApplicationInitializer接口的。

 

 

 

@since Servlet 3.0

public interface ServletContainerInitializer {

    public void onStartup(Set<Class<?>> c, ServletContext ctx)

        throws ServletException; 

}

 

查看此接口的注釋

<p>Implementations of this interface must be declared by a JAR file * resource located inside the <tt>META-INF/services</tt> directory and * named for the fully qualified class name of this interface, and will be * discovered using the runtime's service provider lookup mechanism
 * or a container specific mechanism that is semantically equivalent to * it.

大概意思是講 必須在該接口所在項目的META-INF/services/文件夾下 生成一個文件名字為javax.serlvet.ServletContainerInitializer的文件,內容要與ServletContainerInitializer接口的實現類的全路徑一樣才能被發現。

仔細看spring-web包下 有類似的結構。聲明為了javax.servlet.ServletContainerInitializer的文件,內容為 org.springframework.web.SpringServletContainerInitializer

日志來自於實現類:SpringServletContainerInitializer上一段源碼:

 
@Override
	public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

		if (webAppInitializerClasses != null) {
			for (Class<?> waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						initializers.add((WebApplicationInitializer) waiClass.newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		AnnotationAwareOrderComparator.sort(initializers);
		servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);

		for (WebApplicationInitializer initializer : initializers) {
			initializer.onStartup(servletContext);
		}
	}

  

因為沒有使用基於servlet3.0規范的類,所以有這一條日志。
 

 

 

 

log:

 

Initializing Spring root WebApplicationContext

 

解釋:日志是由類

WebApplicationContextorg.springframework.web.context.ContextLoader.initWebApplicationContext(ServletContext servletContext)打印的,contextLoader作為ContextLoaderListener的private 變量。標識着啟動wac。核心代碼在wac.refresh()中。

值得注意的是注冊核心類之前,會先處理beanFactory的PostProcesors類。

這些類一般都實現了 

BeanFactoryPostProcessor 這個接口。通常講抽象類PropertyResourceConfigurer比較重要。

org.springframework.beans.factory.config.PropertyResourceConfigurer

源碼注釋:
/* Allows for custom modification of an application context's bean definitions, * adapting the bean property values of the context's underlying bean factory. * * <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in * their bean definitions and apply them before any other beans get created. * * <p>Useful for custom config files targeted at system administrators that * override bean properties configured in the application context.

  */

 

 

LOG:

2017-02-25 19:29:08:719  INFO  [mvc.annotation.DefaultAnnotationHandlerMapping] Mapped URL path

 

解釋:

啟動wac時,會由讀取@RequestMapping 注解拼接url ,並緩存 {url,method}的映射關系。

 

LOG:

二月 25, 2017 7:40:29 下午 org.apache.catalina.core.ApplicationContext log

信息: Initializing Spring FrameworkServlet 'led'

2017-02-25 19:40:29:584  INFO  [web.servlet.DispatcherServlet] FrameworkServlet 'led': initialization started

2017-02-25 19:40:29:603  INFO  [context.support.XmlWebApplicationContext] Refreshing WebApplicationContext for namespace 'led-servlet': startup date [Sat Feb 25 19:40:29 CST 2017]; parent: Root WebApplicationContext

2017-02-25 19:40:29:605  INFO  [factory.xml.XmlBeanDefinitionReader] Loading XML bean definitions from ServletContext resource [/WEB-INF/led-servlet.xml]

 

 

 

解釋:開始啟動servlet,配置為DispatcherServlet 並執行父類 FrameworkServlet 的父類 HttpServletBean的init方法,並鈎子調用FrameworkServlet的initServletBean()創建servlet容器 放到servletContext

setAttribute(Framework.class.getName()+".CONTEXT"+ServletName,WAC);並且將WAC的parent設置為ContextLoaderListener創建的WAC。

 

 

至此SpringMVC啟動完畢。

更加詳細的內容下一篇隨筆。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM