在Servlet3.0的规范中,可以通过实现ServletContainerInitializer
接口,在web容器启动时给第三方组件做一些初始化的工作,第三方组件使用ServletContainerInitializer
接口,就必须在对应的jar包的META-INF/services
目录创建一个名为javax.servlet.ServletContainerInitializer
的文件,文件内容指定具体的ServletContainerInitializer
实现类。
一般伴随着ServletContainerInitializer一起使用的还有HandlesTypes注解,通过HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializerde的onStartup方法作为参数传入。
public interface ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}
SpringMVC的实现类 在spring-web工程下,META-INF/services/javax.servlet.ServletContainerInitializer
org.springframework.web.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;
}
AnnotationAwareOrderComparator.sort(initializers);
servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
SpringMVC的实现类SpringServletContainerInitializer
,SpringServletContainerInitializer
类上面的注解@HandlesTypes(WebApplicationInitializer.class)
,会将实现了WebApplicationInitializer
接口的类以onStartup
方法的参数的形式传入,所以只需要我们在自己的工程下面,实现WebApplicationInitializer
就行
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
return null;
}
}
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {"com.chenbk.test"})
public class WebMvcConfig {
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
AbstractAnnotationConfigDispatcherServletInitializer
是WebApplicationInitializer
的抽像实现,可以直接继承AbstractAnnotationConfigDispatcherServletInitializer