标签:准备 www [] mem use sub 含义 htm vat
最近打算花点时间好好看看spring的源码,然而现在Spring的源码经过迭代的版本太多了,比较庞大,看起来比较累,所以准备从最初的版本(interface21)开始入手,仅用于学习,理解其设计思想,后续慢慢研究其每次版本变更的内容。。。
先从interface21的一个典型web工程例子看起,宠物诊所 - petclinic,因为该工程基本涵盖了Spring的APO、IOC、JDBC、Web MVC、事务、国际化、主题切换、参数校验等主要功能。。。
继上一篇,了解完ContextLoaderListener(加载Spring Web Application Context)的流程后,看看Spring mvc的关键控制器 - DispatcherServlet初始化流程是如何的~~~~~~~
<servlet> <servlet-name>petclinic</servlet-name> <servlet-class>com.interface21.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>petclinic</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping>
这里有一个地方需要注意下,load-on-startup的配置,关于该Servlet参数的含义,可以先看下web-app_2_3.dtd文件中的解释,如下,大致意思就是,如果没配置load-on-startup或该值为负数,则servlet容器可以自由选择什么时候加载该servlet(实例化并执行Servlet的init方法),如果为0或正数,则必须在容器启动时加载Servlet并执行其init方法,且数值越小的Servlet优先加载,回过头看我们的DispatcherServlet,由于load-on-startup配置成1,所以会在启动的时候,执行init方法,即本文要关注的DispatcherServlet初始化流程:
<!-- The load-on-startup element indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the web application. The optional contents of these element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses. If the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed. The container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-start-up value. Used in: servlet -->
执行的入口在HttpServletBean类的init方法,由于DispatcherServlet的load-on-startup参数配置成1,所以在Servlet容器(tomcat)启动时,会自动调用该Servlet的init方法。
步骤描述:
public final void init() throws ServletException { this.identifier = "Servlet with name ‘" + getServletConfig().getServletName() + "‘ "; logger.info(getIdentifier() + "entering init..."); // Set bean properties try { PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), requiredProperties); BeanWrapper bw = new BeanWrapperImpl(this); bw.setPropertyValues(pvs); logger.debug(getIdentifier() + "properties bound OK"); // Let subclasses do whatever initialization they like initServletBean(); logger.info(getIdentifier() + "configured successfully"); } catch (BeansException ex) { String mesg = getIdentifier() + ": error setting properties from ServletConfig"; logger.error(mesg, ex); throw new ServletException(mesg, ex); } catch (Throwable t) { // Let subclasses throw unchecked exceptions String mesg = getIdentifier() + ": initialization error"; logger.error(mesg, t); throw new ServletException(mesg, t); } }
protected final void initServletBean() throws ServletException { long startTime = System.currentTimeMillis(); logger.info("Framework servlet ‘" + getServletName() + "‘ init"); this.webApplicationContext = createWebApplicationContext(); initFrameworkServlet(); long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Framework servlet ‘" + getServletName() + "‘ init completed in " + elapsedTime + " ms"); }
private WebApplicationContext createWebApplicationContext() throws ServletException { getServletContext().log("Loading WebApplicationContext for servlet ‘" + getServletName() + "‘"); ServletContext sc = getServletConfig().getServletContext(); WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(sc); String namespace = getNamespace(); WebApplicationContext waca = (this.contextClass != null) ? instantiateCustomWebApplicationContext(this.contextClass, parent, namespace) : new XmlWebApplicationContext(parent, namespace); logger.info("Loading WebApplicationContext for servlet ‘" + getServletName() + "‘: using context class ‘" + waca.getClass().getName() + "‘"); waca.setServletContext(sc); if (this.publishContext) { // Publish the context as a servlet context attribute String attName = getServletContextAttributeName(); sc.setAttribute(attName, waca); logger.info("Bound context of servlet ‘" + getServletName() + "‘ in global ServletContext with name ‘" + attName + "‘"); } return waca; }
protected void initFrameworkServlet() throws ServletException { initLocaleResolver(); initThemeResolver(); initHandlerMappings(); initHandlerAdapters(); initViewResolver(); }
private void initLocaleResolver() throws ServletException { try { this.localeResolver = (LocaleResolver) getWebApplicationContext().getBean(LOCALE_RESOLVER_BEAN_NAME); logger.info("Loaded locale resolver [" + this.localeResolver + "]"); } catch (NoSuchBeanDefinitionException ex) { // We need to use the default this.localeResolver = new AcceptHeaderLocaleResolver(); logger.info("Unable to locate locale resolver with name ‘" + LOCALE_RESOLVER_BEAN_NAME + "‘: using default [" + this.localeResolver + "]"); } catch (BeansException ex) { // We tried and failed to load the LocaleResolver specified by a bean throw new ServletException("Fatal error loading locale resolver with name ‘" + LOCALE_RESOLVER_BEAN_NAME + "‘: using default", ex); } }
private void initThemeResolver() throws ServletException { try { this.themeResolver = (ThemeResolver) getWebApplicationContext().getBean(THEME_RESOLVER_BEAN_NAME); logger.info("Loaded theme resolver [" + this.themeResolver + "]"); } catch (NoSuchBeanDefinitionException ex) { // We need to use the default this.themeResolver = new FixedThemeResolver(); logger.info("Unable to locate theme resolver with name ‘" + THEME_RESOLVER_BEAN_NAME + "‘: using default [" + this.themeResolver + "]"); } catch (BeansException ex) { // We tried and failed to load the ThemeResolver specified by a bean throw new ServletException("Fatal error loading theme resolver with name ‘" + THEME_RESOLVER_BEAN_NAME + "‘: using default", ex); } }
private void initHandlerMappings() throws ServletException { this.handlerMappings = new ArrayList(); // Find all HandlerMappings in the ApplicationContext String[] hms = getWebApplicationContext().getBeanDefinitionNames(HandlerMapping.class); for (int i = 0; i < hms.length; i++) { initHandlerMapping(hms[i]); logger.info("Loaded handler mapping [" + hms[i] + "]"); } // Ensure we have at least one HandlerMapping, by registering // a default HandlerMapping if no other mappings are found. if (this.handlerMappings.isEmpty()) { initDefaultHandlerMapping(); logger.info("No HandlerMappings found in servlet ‘" + getServletName() + "‘: using default"); } else { // We keep HandlerMappings in sorted order Collections.sort(this.handlerMappings, new OrderComparator()); } }
private void initDefaultHandlerMapping() throws ServletException { try { HandlerMapping hm = new BeanNameUrlHandlerMapping(); hm.setApplicationContext(getWebApplicationContext()); this.handlerMappings.add(hm); } catch (ApplicationContextException ex) { throw new ServletException("Error initializing default HandlerMapping: " + ex.getMessage(), ex); } }
private void initHandlerAdapters() throws ServletException { this.handlerAdapters = new ArrayList(); String[] has = getWebApplicationContext().getBeanDefinitionNames(HandlerAdapter.class); for (int i = 0; i < has.length; i++) { initHandlerAdapter(has[i]); logger.info("Loaded handler adapter [" + has[i] + "]"); } // Ensure we have at least one HandlerAdapter, by registering // a default HandlerAdapter if no other adapters are found. if (this.handlerAdapters.isEmpty()) { initDefaultHandlerAdapter(); logger.info("No HandlerAdapters found in servlet ‘" + getServletName() + "‘: using default"); } else { // We keep HandlerAdapters in sorted order Collections.sort(this.handlerAdapters, new OrderComparator()); } }
private void initDefaultHandlerAdapter() throws ServletException { try { HandlerAdapter ha = new SimpleControllerHandlerAdapter(); ha.setApplicationContext(getWebApplicationContext()); this.handlerAdapters.add(ha); } catch (ApplicationContextException ex) { throw new ServletException("Error initializing default HandlerAdapter: " + ex.getMessage(), ex); } }
private void initViewResolver() throws ServletException { try { this.viewResolver = (ViewResolver) getWebApplicationContext().getBean(VIEW_RESOLVER_BEAN_NAME); logger.info("Loaded view resolver [" + viewResolver + "]"); } catch (NoSuchBeanDefinitionException ex) { // We need to use the default this.viewResolver = new InternalResourceViewResolver(); try { this.viewResolver.setApplicationContext(getWebApplicationContext()); } catch (ApplicationContextException ex2) { throw new ServletException("Fatal error initializing default ViewResolver"); } logger.info("Unable to locate view resolver with name ‘" + VIEW_RESOLVER_BEAN_NAME + "‘: using default [" + this.viewResolver + "]"); } catch (BeansException ex) { // We tried and failed to load the ViewResolver specified by a bean throw new ServletException("Fatal error loading view resolver: bean with name ‘" + VIEW_RESOLVER_BEAN_NAME + "‘ is required in servlet ‘" + getServletName() + "‘: using default", ex); } }
另外可以关注下该Servlet的销毁方法,类似的,也是执行一些资源销毁等操作,销毁工厂创建的单例bean对象,发布ContextClosedEvent事件等;
public void destroy() { getServletContext().log("Closing WebApplicationContext for servlet ‘" + getServletName() + "‘"); getWebApplicationContext().close(); }
public void close() { logger.info("Closing application context [" + getDisplayName() + "]"); // destroy all cached singletons in this context, // invoking DisposableBean.destroy and/or "destroy-method" getBeanFactory().destroySingletons(); // publish respective event publishEvent(new ContextClosedEvent(this)); }
https://github.com/peterchenhdu/interface21
interface21 - web - DispatcherServlet(DispatcherServlet初始化流程)
标签:准备 www [] mem use sub 含义 htm vat
原文地址:https://www.cnblogs.com/chenpi/p/9539451.html