Spring 启动分析(1)
2017-01-11 00:00
162 查看
摘要: spring mvc 由DispatchServlet初始化部分
Spring MVC 启动记录(1)
1、
默认的初始化就是一个DispatchServlet,这个serlet的初始化过程就是整个spring mvc启动的过程。
1-1、默认初始化父类的init方法
GenericServlet的init
然后调用子类HttpServletBean复写的init方法
然后调用initServletBean方法,触发子类FrameworkServlet的initServletBean方法调用
其中调用到本地方法initWebApplicationContext方法
其中getWebApplicationContext的方法
findWebApplicationContext方法如下:在之前的基础上按照attributeName找不到则全部遍历
没有则进一步创建
其中获取contextClass是由FrameworkServlet的本地属性定义
判断完类型后初始化 XmlWebApplicationContext.class这个类
调用BeanUtils的instanceClass方法
直接 获取ServletContext 中的getAttribute调用是否有初始化过的ApplicationContext对象
进而初始化XmlWebApplicationContext类
该类图如下
只有三个默认属性,集成如下,顾初始化所以的父类构造器,继承如下
初始化web xml中的severlet配置到spring的beanwrapper中
Spring MVC 启动记录(1)
1、
默认的初始化就是一个DispatchServlet,这个serlet的初始化过程就是整个spring mvc启动的过程。
1-1、默认初始化父类的init方法
GenericServlet的init
public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } public void init() throws ServletException { }
然后调用子类HttpServletBean复写的init方法
public final void init() throws ServletException { if (logger.isDebugEnabled()) { logger.debug("Initializing servlet '" + getServletName() + "'"); } // Set bean properties from init parameters. try { PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansException ex) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); throw ex; } // Let subclasses do whatever initialization they like. initServletBean(); if (logger.isDebugEnabled()) { logger.debug("Servlet '" + getServletName() + "' configured successfully"); } }
然后调用initServletBean方法,触发子类FrameworkServlet的initServletBean方法调用
protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); if (this.logger.isInfoEnabled()) { this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started"); } long startTime = System.currentTimeMillis(); try { this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); } catch (ServletException ex) { this.logger.error("Context initialization failed", ex); throw ex; } catch (RuntimeException ex) { this.logger.error("Context initialization failed", ex); throw ex; } if (this.logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " + elapsedTime + " ms"); } }
其中调用到本地方法initWebApplicationContext方法
protected WebApplicationContext initWebApplicationContext() { //获取rootContext 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); } } } //为空则进一步获取 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. onRefresh(wac); } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); if (this.logger.isDebugEnabled()) { this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + "' as ServletContext attribute with name [" + attrName + "]"); } } return wac; }
其中getWebApplicationContext的方法
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); } public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { Assert.notNull(sc, "ServletContext must not be null"); Object attr = sc.getAttribute(attrName); if (attr == null) { return null; } if (attr instanceof RuntimeException) { throw (RuntimeException) attr; } if (attr instanceof Error) { throw (Error) attr; } if (attr instanceof Exception) { throw new IllegalStateException((Exception) attr); } if (!(attr instanceof WebApplicationContext)) { throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr); } return (WebApplicationContext) attr; }
findWebApplicationContext方法如下:在之前的基础上按照attributeName找不到则全部遍历
public static WebApplicationContext findWebApplicationContext(ServletContext sc) { WebApplicationContext wac = getWebApplicationContext(sc); if (wac == null) { Enumeration<String> attrNames = sc.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = attrNames.nextElement(); Object attrValue = sc.getAttribute(attrName); if (attrValue instanceof WebApplicationContext) { if (wac != null) { throw new IllegalStateException("No unique WebApplicationContext found: more than one " + "DispatcherServlet registered with publishContext=true?"); } wac = (WebApplicationContext) attrValue; } } } return wac; }
没有则进一步创建
FrameworkServlet的方法 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) { return createWebApplicationContext((ApplicationContext) parent); } protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) { Class<?> contextClass = getContextClass(); //默认的context class XmlWebApplicationContext.class; if (this.logger.isDebugEnabled()) { this.logger.debug("Servlet with name '" + getServletName() + "' will try to create custom WebApplicationContext context of class '" + contextClass.getName() + "'" + ", using parent context [" + parent + "]"); } 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); wac.setConfigLocation(getContextConfigLocation()); configureAndRefreshWebApplicationContext(wac); return wac; }
其中获取contextClass是由FrameworkServlet的本地属性定义
public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
判断完类型后初始化 XmlWebApplicationContext.class这个类
调用BeanUtils的instanceClass方法
BeanUtils //检查是否为接口或者为空,获取构造器反射类进一步调用 public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException { Assert.notNull(clazz, "Class must not be null"); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { return instantiateClass(clazz.getDeclaredConstructor()); } catch (NoSuchMethodException ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } //暴力破解私有构造,调用Constructor实例化一个实例 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { Assert.notNull(ctor, "Constructor must not be null"); try { ReflectionUtils.makeAccessible(ctor); return ctor.newInstance(args); } catch (InstantiationException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Is it an abstract class?", ex); } catch (IllegalAccessException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Is the constructor accessible?", ex); } catch (IllegalArgumentException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Illegal arguments for constructor", ex); } catch (InvocationTargetException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Constructor threw exception", ex.getTargetException()); } }
直接 获取ServletContext 中的getAttribute调用是否有初始化过的ApplicationContext对象
进而初始化XmlWebApplicationContext类
该类图如下
只有三个默认属性,集成如下,顾初始化所以的父类构造器,继承如下
初始化web xml中的severlet配置到spring的beanwrapper中
相关文章推荐
- 转:Spring源码分析:IOC容器在web容器中的启动
- spring启动component-scan类扫描加载过程---源码分析
- spring boot应用启动原理分析
- 【Spring启动过程分析】(1)启动流程简介
- spring boot应用启动原理分析
- Spring源代码分析之(二):IOC容器在web容器中的启动
- SpringBoot-Loader源码分析系列1:启动&读取MANIFEST.MF文件
- Spring Boot 启动原理分析
- spring启动component-scan类扫描加载过程---源码分析
- spring boot应用启动原理分析
- Spring-Spring容器启动各项操作窥探(AbstractApplicationContext#refesh()执行逻辑分析)
- 四 spring 源码分析--- 容器启动 时序图
- spring启动component-scan类扫描加载过程---源码分析
- Web容器启动时加载Spring分析
- Spring揭秘 读书笔记 七 BeanFactory的启动分析
- spring启动component-scan类扫描加载过程---源码分析
- 自我分析-Spring IOC在Web应用的启动和销毁
- 【Spring】Spring的IOC(控制反转)/DI(依赖注入)原理(三):Spring启动加载配置文件源码分析
- Spring Boot应用启动原理分析(转)
- SpringBoot-Loader源码分析系列2:启动 new JarLauncher().launch(args)的.launch(args)部分