大家应该都已经知道Spring 3.1对无web.xml式基于代码配置的servlet3.0应用。通过spring的api或是网络上高手们的博文,也一定很快就学会并且加到自己的应用中去了。PS:如果还没,也可以小小参考一下鄙人的上一篇文章<<探 Spring 3.1之无web.xml式 基于代码配置的servlet3.0应用>>。

经过一天的深度research, 我了解,理解以及重现了springframework的那一小段代码。

OK,第一步,入手点,WebApplicationInitializer接口。因为我们只需实现这个接口覆写它的一个方法,就可以做到配置web.xml同样的功效。看它的源码,其实看和不看没什么两样:

Java代码 复制代码 收藏代码
  1. package org.springframework.web;
  2.  
  3. import javax.servlet.ServletContext;
  4. import javax.servlet.ServletException;
  5. public interface WebApplicationInitializer {
  6. void onStartup(ServletContext servletContext) throws ServletException;
  7. }

package org.springframework.web;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
public interface WebApplicationInitializer {
	void onStartup(ServletContext servletContext) throws ServletException;
}


就这么点儿,有效代码5行,弄地我一头雾水,就是一个普通接口,声明了一个方法。连注解都没有,server是怎么找到实现了它的类的?如果这样,何不找我定义的其它接口(的实现类完成配置工作)呢。可见现在java的解耦技术,真令人汗颜。
第二步,这个接口旁边(同包)有个SpringServletContainerInitializer, 看下它是何方神圣吧:

Java代码 复制代码 收藏代码
  1. package org.springframework.web;
  2.  
  3. import java.lang.reflect.Modifier;
  4. import java.util.Collections;
  5. import java.util.LinkedList;
  6. import java.util.List;
  7. import java.util.ServiceLoader;
  8. import java.util.Set;
  9. import javax.servlet.ServletContainerInitializer;
  10. import javax.servlet.ServletContext;
  11. import javax.servlet.ServletException;
  12. import javax.servlet.annotation.HandlesTypes;
  13.  
  14. import org.springframework.core.annotation.AnnotationAwareOrderComparator;
  15.  
  16. @HandlesTypes(WebApplicationInitializer.class)
  17. public class SpringServletContainerInitializer implements ServletContainerInitializer {
  18. public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
  19. throws ServletException {
  20.  
  21. List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
  22. if (webAppInitializerClasses != null) {
  23. for (Class<?> waiClass : webAppInitializerClasses) {
  24. // Be defensive: Some servlet containers provide us with invalid classes,
  25. // no matter what @HandlesTypes says...
  26. if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
  27. try {
  28. initializers.add((WebApplicationInitializer) waiClass.newInstance());
  29. }
  30. catch (Throwable ex) {
  31. throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
  32. }
  33. }
  34. }
  35. }
  36.  
  37. if (initializers.isEmpty()) {
  38. servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
  39. return;
  40. }
  41.  
  42. Collections.sort(initializers, new AnnotationAwareOrderComparator());
  43. servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);
  44.  
  45. for (WebApplicationInitializer initializer : initializers) {
  46. initializer.onStartup(servletContext);
  47. }
  48. }
  49.  
  50. }

package org.springframework.web;

import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;

import org.springframework.core.annotation.AnnotationAwareOrderComparator;

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
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;
		}

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

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

}