前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。@pdai
  • Spring框架系列(13) - SpringMVC实现原理之DispatcherServlet的初始化过程

    • DispatcherServlet和ApplicationContext有何关系?
    • DispatcherServlet是如何初始化的?

      • init
      • initWebApplicationContext
      • refresh
      • initHanlderxxx
    • 更多文章

DispatcherServlet和ApplicationContext有何关系?

DispatcherServlet 作为一个 Servlet,须要依据 Servlet 标准应用 Java 配置或 web.xml 申明和映射。反过来,DispatcherServlet 应用 Spring 配置来发现申请映射、视图解析、异样解决等等所需的委托组件。那它和ApplicationContext有和关系呢?如下内容能够参考官网-SpringMVC文档

DispatcherServlet 须要 WebApplicationContext(继承自 ApplicationContext) 来配置。WebApplicationContext 能够链接到ServletContext 和 Servlet。因为绑定了 ServletContext,这样应用程序就能够在须要的时候应用 RequestContextUtils 的静态方法拜访 WebApplicationContext。

大多数应用程序只有一个WebApplicationContext,除此之外也能够一个Root WebApplicationContext 被多个 Servlet实例,而后各自领有本人的Servlet WebApplicationContext 配置。

Root WebApplicationContext 蕴含须要共享给多个 Servlet 实例的数据源和业务服务根底 Bean。这些 Bean 能够在 Servlet 特定的范畴被继承或笼罩。

(PS:官网上的这张图能够能够帮忙你构建DispatcherServlet和ApplicationContext在设计上的认知,这一点对于了解DispatcherServlet的设计和初始化过程十分重要)

DispatcherServlet是如何初始化的?

DispatcherServlet首先是Sevlet,Servlet有本人的生命周期的办法(init,destory等),那么咱们在看DispatcherServlet初始化时首先须要看源码中DispatcherServlet的类结构设计。

首先咱们看DispatcherServlet的类构造关系,在这个类依赖构造中找到init的办法

很容易找到init()的办法位于HttpServletBean中,而后跑Spring根底 - SpringMVC申请流程和案例中的代码,在init办法中打断点。

init

init()办法如下, 次要读取web.xml中servlet参数配置,并将交给子类办法initServletBean()持续初始化

/**  * Map config parameters onto bean properties of this servlet, and  * invoke subclass initialization.  * @throws ServletException if bean properties are invalid (or required  * properties are missing), or if subclass initialization fails.  */@Overridepublic final void init() throws ServletException {  // 读取web.xml中的servlet配置  PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);  if (!pvs.isEmpty()) {    try {      // 转换成BeanWrapper,为了方便使用Spring的属性注入性能      BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);      // 注入Resource类型须要依赖于ResourceEditor解析,所以注册Resource类关联到ResourceEditor解析器      ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());      bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));      // 更多的初始化能够让子类去拓展      initBeanWrapper(bw);      // 让spring注入namespace,contextConfigLocation等属性      bw.setPropertyValues(pvs, true);    }    catch (BeansException ex) {      if (logger.isErrorEnabled()) {        logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);      }      throw ex;    }  }  // 让子类去拓展  initServletBean();}

读取配置能够从下图看出,正是初始化了咱们web.xml中配置

再看下initServletBean()办法,位于FrameworkServlet类中

/**  * Overridden method of {@link HttpServletBean}, invoked after any bean properties  * have been set. Creates this servlet's WebApplicationContext.  */@Overrideprotected final void initServletBean() throws ServletException {  getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");  if (logger.isInfoEnabled()) {    logger.info("Initializing Servlet '" + getServletName() + "'");  }  long startTime = System.currentTimeMillis();  try {    // 最重要的是这个办法    this.webApplicationContext = initWebApplicationContext();    // 能够让子类进一步拓展    initFrameworkServlet();  }  catch (ServletException | RuntimeException ex) {    logger.error("Context initialization failed", ex);    throw ex;  }  if (logger.isDebugEnabled()) {    String value = this.enableLoggingRequestDetails ?        "shown which may lead to unsafe logging of potentially sensitive data" :        "masked to prevent unsafe logging of potentially sensitive data";    logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +        "': request parameters and headers will be " + value);  }  if (logger.isInfoEnabled()) {    logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");  }}

initWebApplicationContext

initWebApplicationContext用来初始化和刷新WebApplicationContext。

initWebApplicationContext() 办法如下

/**  * Initialize and publish the WebApplicationContext for this servlet.  * <p>Delegates to {@link #createWebApplicationContext} for actual creation  * of the context. Can be overridden in subclasses.  * @return the WebApplicationContext instance  * @see #FrameworkServlet(WebApplicationContext)  * @see #setContextClass  * @see #setContextConfigLocation  */protected WebApplicationContext initWebApplicationContext() {  WebApplicationContext rootContext =      WebApplicationContextUtils.getWebApplicationContext(getServletContext());  WebApplicationContext wac = null;  // 如果在构造函数曾经被初始化  if (this.webApplicationContext != null) {    // A context instance was injected at construction time -> use it    wac = this.webApplicationContext;    if (wac instanceof ConfigurableWebApplicationContext) {      ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;      if (!cwac.isActive()) {        // The context has not yet been refreshed -> provide services such as        // setting the parent context, setting the application context id, etc        if (cwac.getParent() == null) {          // The context instance was injected without an explicit parent -> set          // the root application context (if any; may be null) as the parent          cwac.setParent(rootContext);        }        configureAndRefreshWebApplicationContext(cwac);      }    }  }  // 没有在构造函数中初始化,则尝试通过contextAttribute初始化  if (wac == null) {    // No context instance was injected at construction time -> see if one    // has been registered in the servlet context. If one exists, it is assumed    // that the parent context (if any) has already been set and that the    // user has performed any initialization such as setting the context id    wac = findWebApplicationContext();  }  // 还没有的话,只能从新创立了  if (wac == null) {    // No context instance is defined for this servlet -> create a local one    wac = createWebApplicationContext(rootContext);  }  if (!this.refreshEventReceived) {    // Either the context is not a ConfigurableApplicationContext with refresh    // support or the context injected at construction time had already been    // refreshed -> trigger initial onRefresh manually here.    synchronized (this.onRefreshMonitor) {      onRefresh(wac);    }  }  if (this.publishContext) {    // Publish the context as a servlet context attribute.    String attrName = getServletContextAttributeName();    getServletContext().setAttribute(attrName, wac);  }  return wac;}

webApplicationContext只会初始化一次,顺次尝试构造函数初始化,没有则通过contextAttribute初始化,仍没有则创立新的

创立的createWebApplicationContext办法如下

/**  * Instantiate the WebApplicationContext for this servlet, either a default  * {@link org.springframework.web.context.support.XmlWebApplicationContext}  * or a {@link #setContextClass custom context class}, if set.  * <p>This implementation expects custom contexts to implement the  * {@link org.springframework.web.context.ConfigurableWebApplicationContext}  * interface. Can be overridden in subclasses.  * <p>Do not forget to register this servlet instance as application listener on the  * created context (for triggering its {@link #onRefresh callback}, and to call  * {@link org.springframework.context.ConfigurableApplicationContext#refresh()}  * before returning the context instance.  * @param parent the parent ApplicationContext to use, or {@code null} if none  * @return the WebApplicationContext for this servlet  * @see org.springframework.web.context.support.XmlWebApplicationContext  */protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {  Class<?> contextClass = getContextClass();  if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {    throw new ApplicationContextException(        "Fatal initialization error in servlet with name '" + getServletName() +        "': custom WebApplicationContext class [" + contextClass.getName() +        "] is not of type ConfigurableWebApplicationContext");  }  // 通过反射形式初始化  ConfigurableWebApplicationContext wac =      (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);  wac.setEnvironment(getEnvironment());  wac.setParent(parent);  String configLocation = getContextConfigLocation(); // 就是后面Demo中的springmvc.xml  if (configLocation != null) {    wac.setConfigLocation(configLocation);  }  // 初始化Spring环境  configureAndRefreshWebApplicationContext(wac);  return wac;}

configureAndRefreshWebApplicationContext办法初始化设置Spring环境

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {  // 设置context ID  if (ObjectUtils.identityToString(wac).equals(wac.getId())) {    // The application context id is still set to its original default value    // -> assign a more useful id based on available information    if (this.contextId != null) {      wac.setId(this.contextId);    }    else {      // Generate default id...      wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +          ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());    }  }  // 设置servletContext, servletConfig, namespace, listener...  wac.setServletContext(getServletContext());  wac.setServletConfig(getServletConfig());  wac.setNamespace(getNamespace());  wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));  // The wac environment's #initPropertySources will be called in any case when the context  // is refreshed; do it eagerly here to ensure servlet property sources are in place for  // use in any post-processing or initialization that occurs below prior to #refresh  ConfigurableEnvironment env = wac.getEnvironment();  if (env instanceof ConfigurableWebEnvironment) {    ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());  }  // 让子类去拓展  postProcessWebApplicationContext(wac);  applyInitializers(wac);  // Spring环境初始化完了,就能够初始化DispatcherServlet解决流程中须要的组件了。  wac.refresh();}

refresh

有了webApplicationContext后,就开始刷新了(onRefresh()办法),这个办法是FrameworkServlet提供的模板办法,由子类DispatcherServlet来实现的。

/**  * This implementation calls {@link #initStrategies}.  */@Overrideprotected void onRefresh(ApplicationContext context) {  initStrategies(context);}

刷新次要是调用initStrategies(context)办法对DispatcherServlet中的组件进行初始化,这些组件就是在SpringMVC申请流程中包的次要组件。

/**  * Initialize the strategy objects that this servlet uses.  * <p>May be overridden in subclasses in order to initialize further strategy objects.  */protected void initStrategies(ApplicationContext context) {  initMultipartResolver(context);  initLocaleResolver(context);  initThemeResolver(context);  // 次要看如下三个办法  initHandlerMappings(context);  initHandlerAdapters(context);  initHandlerExceptionResolvers(context);  initRequestToViewNameTranslator(context);  initViewResolvers(context);  initFlashMapManager(context);}

initHanlderxxx

咱们次要看initHandlerXXX相干的办法,它们之间的关系能够看SpringMVC的申请流程:

  1. HandlerMapping是映射处理器
  2. HandlerAdpter是解决适配器,它用来找到你的Controller中的解决办法
  3. HandlerExceptionResolver是当遇到解决异样时的异样解析器

initHandlerMapping办法如下,无非就是获取依照优先级排序后的HanlderMappings, 未来匹配时依照优先级最高的HanderMapping进行解决。

initHandlerAdapters办法和initHandlerExceptionResolvers办法也是相似的,如果没有找到,那就构建默认的。

/**  * Initialize the HandlerAdapters used by this class.  * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,  * we default to SimpleControllerHandlerAdapter.  */private void initHandlerAdapters(ApplicationContext context) {  this.handlerAdapters = null;  if (this.detectAllHandlerAdapters) {    // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.    Map<String, HandlerAdapter> matchingBeans =        BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);    if (!matchingBeans.isEmpty()) {      this.handlerAdapters = new ArrayList<>(matchingBeans.values());      // We keep HandlerAdapters in sorted order.      AnnotationAwareOrderComparator.sort(this.handlerAdapters);    }  }  else {    try {      HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);      this.handlerAdapters = Collections.singletonList(ha);    }    catch (NoSuchBeanDefinitionException ex) {      // Ignore, we'll add a default HandlerAdapter later.    }  }  // Ensure we have at least some HandlerAdapters, by registering  // default HandlerAdapters if no other adapters are found.  if (this.handlerAdapters == null) {    this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);    if (logger.isTraceEnabled()) {      logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +          "': using default strategies from DispatcherServlet.properties");    }  }}/**  * Initialize the HandlerExceptionResolver used by this class.  * <p>If no bean is defined with the given name in the BeanFactory for this namespace,  * we default to no exception resolver.  */private void initHandlerExceptionResolvers(ApplicationContext context) {  this.handlerExceptionResolvers = null;  if (this.detectAllHandlerExceptionResolvers) {    // Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.    Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils        .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);    if (!matchingBeans.isEmpty()) {      this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());      // We keep HandlerExceptionResolvers in sorted order.      AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);    }  }  else {    try {      HandlerExceptionResolver her =          context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);      this.handlerExceptionResolvers = Collections.singletonList(her);    }    catch (NoSuchBeanDefinitionException ex) {      // Ignore, no HandlerExceptionResolver is fine too.    }  }  // Ensure we have at least some HandlerExceptionResolvers, by registering  // default HandlerExceptionResolvers if no other resolvers are found.  if (this.handlerExceptionResolvers == null) {    this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);    if (logger.isTraceEnabled()) {      logger.trace("No HandlerExceptionResolvers declared in servlet '" + getServletName() +          "': using default strategies from DispatcherServlet.properties");    }  }}

最初咱们看下初始化的日志:

21:30:33.163 [RMI TCP Connection(2)-127.0.0.1] INFO org.springframework.web.servlet.DispatcherServlet - Initializing Servlet 'springmvc-demo'21:30:38.242 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.context.support.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'springmvc-demo-servlet'21:30:39.256 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/Users/pdai/pdai/www/tech-pdai-spring-demos/011-spring-framework-demo-springmvc/target/011-spring-framework-demo-springmvc-1.0-SNAPSHOT/WEB-INF/classes/tech/pdai/springframework/springmvc/controller/UserController.class]21:30:39.261 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/Users/pdai/pdai/www/tech-pdai-spring-demos/011-spring-framework-demo-springmvc/target/011-spring-framework-demo-springmvc-1.0-SNAPSHOT/WEB-INF/classes/tech/pdai/springframework/springmvc/dao/UserDaoImpl.class]21:30:39.274 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/Users/pdai/pdai/www/tech-pdai-spring-demos/011-spring-framework-demo-springmvc/target/011-spring-framework-demo-springmvc-1.0-SNAPSHOT/WEB-INF/classes/tech/pdai/springframework/springmvc/service/UserServiceImpl.class]21:30:39.546 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 29 bean definitions from class path resource [springmvc.xml]21:30:39.711 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'21:30:39.973 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'21:30:39.984 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'21:30:39.995 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'21:30:40.003 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'21:30:40.042 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.ui.context.support.UiApplicationContextUtils - Unable to locate ThemeSource with name 'themeSource': using default [org.springframework.ui.context.support.ResourceBundleThemeSource@791af912]21:30:40.052 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userController'21:30:40.136 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userServiceImpl'21:30:40.140 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userDaoImpl'21:30:40.147 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'21:30:40.153 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0'21:30:40.350 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.handler.MappedInterceptor#0'21:30:40.356 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.format.support.FormattingConversionServiceFactoryBean#0'21:30:40.741 [RMI TCP Connection(2)-127.0.0.1] DEBUG _org.springframework.web.servlet.HandlerMapping.Mappings - 'org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0' {/**=org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler@216c0f1f}21:30:40.742 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mvcCorsConfigurations'21:30:40.742 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping'21:30:40.792 [RMI TCP Connection(2)-127.0.0.1] DEBUG _org.springframework.web.servlet.HandlerMapping.Mappings - 'org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping' {}21:30:40.792 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter'21:30:40.793 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter'21:30:40.794 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'localeResolver'21:30:40.796 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'themeResolver'21:30:40.798 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'viewNameTranslator'21:30:40.799 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'flashMapManager'21:30:40.805 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mvcContentNegotiationManager'21:30:40.887 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping'21:30:41.150 [RMI TCP Connection(2)-127.0.0.1] DEBUG _org.springframework.web.servlet.HandlerMapping.Mappings -     t.p.s.s.c.UserController:    { [/user]}: list(HttpServletRequest,HttpServletResponse)21:30:41.202 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - 1 mappings in 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping'21:30:41.202 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter'21:30:41.626 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - ControllerAdvice beans: none21:30:41.738 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mvcUriComponentsContributor'21:30:41.786 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - ControllerAdvice beans: none21:30:41.806 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0'21:30:41.919 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - ControllerAdvice beans: none21:30:41.920 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0'21:30:41.949 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0'21:30:41.967 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'jspViewResolver'21:30:44.214 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected AcceptHeaderLocaleResolver21:30:44.214 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected FixedThemeResolver21:31:02.141 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@d57bc9121:31:03.483 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.support.SessionFlashMapManager@2b4e795e21:44:08.180 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.liveBeansView.mbeanDomain]21:44:08.185 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.liveBeansView.mbeanDomain] not found - trying original name [spring.liveBeansView.mbeanDomain]. javax.naming.NameNotFoundException: 名称[spring.liveBeansView.mbeanDomain]未在此上下文中绑定。找不到[spring.liveBeansView.mbeanDomain]。21:44:08.185 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.liveBeansView.mbeanDomain]21:44:08.185 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [spring.liveBeansView.mbeanDomain] threw NamingException with message: 名称[spring.liveBeansView.mbeanDomain]未在此上下文中绑定。找不到[spring.liveBeansView.mbeanDomain]。. Returning null.21:44:08.195 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data21:44:08.195 [RMI TCP Connection(2)-127.0.0.1] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 815032 ms

更多文章

首先, 从Spring框架的整体架构和组成对整体框架有个认知。
  • Spring根底 - Spring和Spring框架组成

    • Spring是什么?它是怎么诞生的?有哪些次要的组件和外围性能呢? 本文通过这几个问题帮忙你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的外围(IoC和AOP),同时对IoC和AOP进行案例应用剖析。
  • Spring根底 - Spring简略例子引入Spring的外围

    • 上文中咱们简略介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文次要承接上文,向你展现Spring Framework组件的典型利用场景和基于这个场景设计出的简略案例,并以此引出Spring的外围要点,比方IOC和AOP等;在此基础上还引入了不同的配置形式, 如XML,Java配置和注解形式的差别。
  • Spring根底 - Spring外围之管制反转(IOC)

    • 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点; 本节将在此基础上进一步解读IOC的含意以及IOC的应用形式
  • Spring根底 - Spring外围之面向切面编程(AOP)

    • 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了AOP的根底含意,同时以此发散了一些AOP相干知识点; 本节将在此基础上进一步解读AOP的含意以及AOP的应用形式。
基于Spring框架和IOC,AOP的根底,为构建下层web利用,须要进一步学习SpringMVC。
  • Spring根底 - SpringMVC申请流程和案例

    • 前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那咱们如何更好的构建下层的利用呢(比方web 利用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。 本文次要介绍SpringMVC的申请流程和根底案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码剖析
  • Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计

    • 在对IoC有了初步的认知后,咱们开始对IOC的实现原理进行深刻了解。本文将帮忙你站在设计者的角度去看IOC最顶层的结构设计
  • Spring进阶 - Spring IOC实现原理详解之IOC初始化流程

    • 上文,咱们看了IOC设计要点和设计构造;紧接着这篇,咱们能够看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
  • Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

    • 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个ConcurrentHashMap<String, Object>;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文次要钻研的内容?
  • Spring进阶 - Spring AOP实现原理详解之切面实现

    • 前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。
  • Spring进阶 - Spring AOP实现原理详解之AOP代理

    • 上文咱们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上持续介绍,代理(cglib代理和JDK代理)的实现过程。
  • Spring进阶 - Spring AOP实现原理详解之Cglib代理实现

    • 咱们在前文中曾经介绍了SpringAOP的切面实现和创立动静代理的过程,那么动静代理是如何工作的呢?本文次要介绍Cglib动静代理的案例和SpringAOP实现的原理。
  • Spring进阶 - Spring AOP实现原理详解之JDK代理实现

    • 上文咱们学习了SpringAOP Cglib动静代理的实现,本文次要是SpringAOP JDK动静代理的案例和实现局部。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程

    • 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet解决申请的过程

    • 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第二篇:DispatcherServlet解决申请的过程的源码解析。