@HandlesTypes(WebApplicationInitializer.class)publicclassSpringServletContainerInitializerimplementsServletContainerInitializer{/**
* Delegate the {@code ServletContext} to any {@link WebApplicationInitializer}
* implementations present on the application classpath.
* <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)},
* Servlet 3.0+ containers will automatically scan the classpath for implementations
* of Spring's {@code WebApplicationInitializer} interface and provide the set of all
* such types to the {@code webAppInitializerClasses} parameter of this method.
* <p>If no {@code WebApplicationInitializer} implementations are found on the classpath,
* this method is effectively a no-op. An INFO-level log message will be issued notifying
* the user that the {@code ServletContainerInitializer} has indeed been invoked but that
* no {@code WebApplicationInitializer} implementations were found.
* <p>Assuming that one or more {@code WebApplicationInitializer} types are detected,
* they will be instantiated (and <em>sorted</em> if the @{@link
* org.springframework.core.annotation.Order @Order} annotation is present or
* the {@link org.springframework.core.Ordered Ordered} interface has been
* implemented). Then the {@link WebApplicationInitializer#onStartup(ServletContext)}
* method will be invoked on each instance, delegating the {@code ServletContext} such
* that each instance may register and configure servlets such as Spring's
* {@code DispatcherServlet}, listeners such as Spring's {@code ContextLoaderListener},
* or any other Servlet API componentry such as filters.
* @param webAppInitializerClasses all implementations of
* {@link WebApplicationInitializer} found on the application classpath
* @param servletContext the servlet context to be initialized
* @see WebApplicationInitializer#onStartup(ServletContext)
* @see AnnotationAwareOrderComparator
*/@OverridepublicvoidonStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)throws ServletException {
List<WebApplicationInitializer> initializers =newLinkedList<>();if(webAppInitializerClasses != null){for(Class<?> waiClass : webAppInitializerClasses){// 防身:无论@HandlesTypes怎么说,某些servlet容器都会为我们提供无效的类.../**
* 判断waiClass不是接口
* 不是抽象类
* 继承WebApplicationInitializer
*/if(!waiClass.isInterface()&&!Modifier.isAbstract(waiClass.getModifiers())&&
WebApplicationInitializer.class.isAssignableFrom(waiClass)){try{//通过反射拿到构造函数并且实例化保存到容器里
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());}catch(Throwable ex){thrownewServletException("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");// 给实现了PriorityOrdered的类进行排序
AnnotationAwareOrderComparator.sort(initializers);for(WebApplicationInitializer initializer : initializers){// 循环调用onStartup
initializer.onStartup(servletContext);}}}
protectedvoidregisterDispatcherServlet(ServletContext servletContext){//获取servlet名称 子类没有重写默认为dispatcher
String servletName =getServletName();
Assert.hasLength(servletName,"getServletName() must not return null or empty");// 创建servlet应用上下文
WebApplicationContext servletAppContext =createServletApplicationContext();
Assert.notNull(servletAppContext,"createServletApplicationContext() must not return null");// 创建DispatcherServlet
FrameworkServlet dispatcherServlet =createDispatcherServlet(servletAppContext);
Assert.notNull(dispatcherServlet,"createDispatcherServlet(WebApplicationContext) must not return null");
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());// 将DispatcherServlet添加到servlet上下文里面
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);if(registration == null){thrownewIllegalStateException("Failed to register servlet with name '"+ servletName +"'. "+"Check if there is another servlet registered under the same name.");}// 设置优先级为1
registration.setLoadOnStartup(1);// 设置servlet的映射路径
registration.addMapping(getServletMappings());// 设置Servlet或Filter配置为是否支持异步操作。 默认为true
registration.setAsyncSupported(isAsyncSupported());// 获取所有的过滤器
Filter[] filters =getServletFilters();if(!ObjectUtils.isEmpty(filters)){for(Filter filter : filters){//注册过滤器到servlet上下文registerServletFilter(servletContext, filter);}}customizeRegistration(registration);}
protectedvoidcustomizeContext(ServletContext sc, ConfigurableWebApplicationContext wac){// 获取ServletContext里面所有 ApplicationContextInitializer实现的类
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =determineContextInitializerClasses(sc);for(Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses){
Class<?> initializerContextClass =
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);if(initializerContextClass != null &&!initializerContextClass.isInstance(wac)){thrownewApplicationContextException(String.format("Could not apply context initializer [%s] since its generic parameter [%s] "+"is not assignable from the type of application context used by this "+"context loader: [%s]", initializerClass.getName(), initializerContextClass.getName(),
wac.getClass().getName()));}this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass));}
AnnotationAwareOrderComparator.sort(this.contextInitializers);//循环执行initialize方法for(ApplicationContextInitializer<ConfigurableApplicationContext> initializer :this.contextInitializers){
initializer.initialize(wac);}}
refresh只看关键代码,详细的在spring启动流程里有写
publicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry){// 获取该BeanDefinitionRegistry的哈希值int registryId = System.identityHashCode(registry);// 判断registriesPostProcessed是否有该BeanDefinitionRegistryif(this.registriesPostProcessed.contains(registryId)){thrownewIllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against "+ registry);}// 判断factoriesPostProcessed是否有该BeanDefinitionRegistryif(this.factoriesPostProcessed.contains(registryId)){thrownewIllegalStateException("postProcessBeanFactory already called on this post-processor against "+ registry);}// 添加到registriesPostProcessed里面this.registriesPostProcessed.add(registryId);processConfigBeanDefinitions(registry);}