前文咱们有了 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.
*/
@Override
public 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.
*/
@Override
protected 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}.
*/
@Override
protected 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 的申请流程:
- HandlerMapping 是映射处理器
- HandlerAdpter 是 解决适配器,它用来找到你的 Controller 中的解决办法
- 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: none
21: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: none
21: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: none
21: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 AcceptHeaderLocaleResolver
21:30:44.214 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected FixedThemeResolver
21:31:02.141 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@d57bc91
21:31:03.483 [RMI TCP Connection(2)-127.0.0.1] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.support.SessionFlashMapManager@2b4e795e
21: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 data
21: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 对象呢,这是本文次要钻研的内容?
- 上文,咱们看了 IOC 设计要点和设计构造;以及 Spring 如何实现将资源配置(以 xml 配置为例)通过加载,解析,生成 BeanDefination 并注册到 IoC 容器中的;容器中寄存的是 Bean 的定义即 BeanDefinition 放到 beanDefinitionMap 中,实质上是一个
-
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 解决申请的过程的源码解析。