说在前面web
本次主要介绍springmvc配置解析,关注“天河聊架构”微信公众号更多源码解析文章。spring
springmvc配置解析微信
sdervlet容器启动的时候会加载org.springframework.web.SpringServletContainerInitializer这个类,调用初始化类的onStartup方法架构
@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); } }
进入到DispatcherServlet初始化器 org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#onStartup这个方法mvc
@Override public void onStartup(ServletContext servletContext) throws ServletException { //调用上下文加载器初始化类的onStartup方法 super.onStartup(servletContext); //注册DispatcherServlet registerDispatcherServlet(servletContext); }
进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#onStartup,执行ContextLoader初始化器app
@Override public void onStartup(ServletContext servletContext) throws ServletException { registerContextLoaderListener(servletContext); }
进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#registerContextLoaderListener,注册ContextLoader监听器异步
protected void registerContextLoaderListener(ServletContext servletContext) { // 获取上层应用上下文对象 -> WebApplicationContext rootAppContext = createRootApplicationContext(); if (rootAppContext != null) { // 建立上下文加载监听器 ContextLoaderListener listener = new ContextLoaderListener(rootAppContext); listener.setContextInitializers(getRootApplicationContextInitializers()); // 把上下文加载监听器加载到servlet容器 servletContext.addListener(listener); } else { logger.debug("No ContextLoaderListener registered, as " + "createRootApplicationContext() did not return an application context"); } }
进入到这个方法org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#createRootApplicationContextide
@Override protected WebApplicationContext createRootApplicationContext() { //从子类实现中或者从@Configuration、@Component注解配置中获取配置类 Class<?>[] configClasses = getRootConfigClasses(); if (!ObjectUtils.isEmpty(configClasses)) { // 若是没有配置就默认初始化基于注解的web应用上下文类 AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext(); rootAppContext.register(configClasses); return rootAppContext; } else { return null; } }
进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#getRootApplicationContextInitializersspa
protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() { return null; }
返回到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#onStartup这一行debug
// 注册DispatcherServlet registerDispatcherServlet(servletContext);
进入到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#registerDispatcherServlet
protected void registerDispatcherServlet(ServletContext servletContext) { //获取servletName,默认名称是dispatcher String servletName = getServletName(); Assert.hasLength(servletName, "getServletName() must not return empty or null"); //建立servlet程序上下文 -> WebApplicationContext servletAppContext = createServletApplicationContext(); Assert.notNull(servletAppContext, "createServletApplicationContext() did not return an application " + "context for servlet [" + servletName + "]"); //建立DispatcherServlet FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext); //注册servlet上下文初始化器,这里是模板实现 dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers()); //添加DispatcherServlet到servlet容器 ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet); Assert.notNull(registration, "Failed to register servlet with name '" + servletName + "'." + "Check if there is another servlet registered under the same name."); registration.setLoadOnStartup(1); //获取servletMapping实现,这里是抽象实现,注册mapping registration.addMapping(getServletMappings()); //设置是否支持异步,默认支持 registration.setAsyncSupported(isAsyncSupported()); //获取servletFilter,这里是模板实现 Filter[] filters = getServletFilters(); if (!ObjectUtils.isEmpty(filters)) { for (Filter filter : filters) { //注册filter -> registerServletFilter(servletContext, filter); } } //定制化注册,默认是模板实现 customizeRegistration(registration); }
进入到这个方法org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#createServletApplicationContext
@Override protected WebApplicationContext createServletApplicationContext() { //建立基于注解的web应用上下文 AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext(); //从子类实现中或者从@Configuration、@Component注解配置中获取配置类 Class<?>[] configClasses = getServletConfigClasses(); if (!ObjectUtils.isEmpty(configClasses)) { // 注册@Configuration配置的配置加载类到AnnotationConfigWebApplicationContext servletAppContext.register(configClasses); } return servletAppContext; }
进入到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#registerServletFilter
protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) { //获取filteName String filterName = Conventions.getVariableName(filter); //添加filter到servlet容器 Dynamic registration = servletContext.addFilter(filterName, filter); //若是filter注册失败 if (registration == null) { int counter = -1; while (counter == -1 || registration == null) { counter++; //添加filter#0 到servlet容器 registration = servletContext.addFilter(filterName + "#" + counter, filter); //提示有一样的名字的filter已注册过 Assert.isTrue(counter < 100, "Failed to register filter '" + filter + "'." + "Could the same Filter instance have been registered already?"); } } //是否支持异步,默认是 registration.setAsyncSupported(isAsyncSupported()); registration.addMappingForServletNames(getDispatcherTypes(), false, getServletName()); return registration; }
回退到这个方法org.springframework.web.SpringServletContainerInitializer#onStartup
说到最后
本次源码解析仅表明我的观点,仅供参考。