Servlet3中增加了一个ServletContainerInitializer类。
其意义如下:
ServletContainerInitializers (SCIs) are registered via an entry in the file META-INF/services/javax.servlet.ServletContainerInitializer that must be included in the JAR file that contains the SCI implementation.
SCI processing is performed regardless of the setting of metadata-complete. SCI processing can be controlled per JAR file via fragment ordering. If an absolute ordering is defined, the only those JARs included in the ordering will be processed for SCIs. To disable SCI processing completely, an empty absolute ordering may be defined.
SCIs register an interest in annotations (class, method or field) and/or types via the javax.servlet.annotation.HandlesTypes annotation which is added to the class.
ServletContainerInitializer在Spring Web中的实现为org.springframework.web.SpringServletContainerInitializer。所以我们在spring-web模块的META-INF/services/javax.servlet.ServletContainerInitializer中文件找到如下内容:
org.springframework.web.SpringServletContainerInitializer
简单看下SpringServletContainerInitializer的源码,把注释去掉了:
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@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;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
重点就在HandlesTypes了,其会查找classpath中所有指定类的实现类。下面是JavaDoc中的解释:
This annotation is used to declare an array of application classes which are passed to a {@link javax.servlet.ServletContainerInitializer}.
上demo(demo来自参考链接中的文章):
@HandlesTypes({ HttpServlet.class,Filter.class })
public class CustomServletContainerInitializer implements
ServletContainerInitializer {
public void onStartup(Set<Class<?>> classes, ServletContext servletContext)
throws ServletException {
for(Class c : classes)
System.out.println(c.getName());
}
}
按照JavaEE的容器规范,容器启动时会依次处理每个ServletContainerInitializer的HandlesTypes注解,然后分别调用所有ServletContainerInitializer对象的onStartup方法,并将处理HandlesTypes注解得到的类数组,传递给ServletContainerInitializer的onStartup方法。
参考:
ServletContainerInitializer初始化器
servlet 3.0笔记之servlet的动态注册
自建一个WebApplicationInitializer