Spring MVC - 整体结构

原创
2017/08/25 10:11
阅读数 7

整体结构

  • XXXAware:在spring中表示感知,如果在某个类中需要XXX,就可以通过实现XXXAware接口高速spring,spring通过接口的唯一方法setXXX。
  • XXXCappable:表示具有提供XXX的能力,spring需要XXX时通过getXXX()获得。

HttpServletBean使用的是StandardServletEnvironment。

  

  1. ServletConfigPropertiesSource:封装的是ServletConfig。
  2. ServletContextPropertiesSource:封装的是ServletContext。
  3. JndiPropertiesSource:存放的是Jndi。
  4. MapPropertiesSource:存放的是虚拟机属性。
  5. SystemEnvironmentPropertiesSource:存放的是系统环境变量。

 

 

HttpServletBean

重写GenericServlet的模板方法init()。 

    public final void init() throws ServletException {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Initializing servlet '" + this.getServletName() + "'");
        }

        try {
//将servlet中配置的参数封装到pvs
            PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
            ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
            bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
//模板方法,子类(DispatcherServlet)中调用(),bw代表DispatcherServlet
//但是子类未使用
            this.initBeanWrapper(bw);
//将配置的初始化参数设置到DispatcherServlet
            bw.setPropertyValues(pvs, true);
        } catch (BeansException var4) {
            this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
            throw var4;
        }

//模板方法,子类初始化入口
        this.initServletBean();
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Servlet '" + this.getServletName() + "' configured successfully");
        }

    }

 

 

FrameworkServlet

初始化入口为initServletBean()。

    protected final void initServletBean() throws ServletException {
        this.getServletContext().log("Initializing Spring FrameworkServlet '" + this.getServletName() + "'");
        if(this.logger.isInfoEnabled()) {
            this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization started");
        }

        long startTime = System.currentTimeMillis();

        try {
            this.webApplicationContext = this.initWebApplicationContext();
            this.initFrameworkServlet();
        } catch (ServletException var5) {
            this.logger.error("Context initialization failed", var5);
            throw var5;
        } catch (RuntimeException var6) {
            this.logger.error("Context initialization failed", var6);
            throw var6;
        }

        if(this.logger.isInfoEnabled()) {
            long elapsedTime = System.currentTimeMillis() - startTime;
            this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization completed in " + elapsedTime + " ms");
        }

    }

核心代码就两句,initFrameworkServlet()是模板方法,但是子类并没有使用。那么主要的作用就是初始化webApplicationContext。

    protected WebApplicationContext initWebApplicationContext() {
//默认情况spring会将自己的容器设置为ServletContext的属性,直接通过ServletContex.getAttribute(key)获得容器
        WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
        WebApplicationContext wac = null;
//第一种
//构造方法中已经设置,只需要对其进行一些设置
        if(this.webApplicationContext != null) {
            wac = this.webApplicationContext;
            if(wac instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
                if(!cwac.isActive()) {
                    if(cwac.getParent() == null) {
                        cwac.setParent(rootContext);
                    }

                    this.configureAndRefreshWebApplicationContext(cwac);
                }
            }
        }
//第二种
        if(wac == null) {
            wac = this.findWebApplicationContext();
        }
//第三种,自己创建
        if(wac == null) {
            wac = this.createWebApplicationContext(rootContext);
        }

        if(!this.refreshEventReceived) {
            this.onRefresh(wac);
        }

        if(this.publishContext) {
            String attrName = this.getServletContextAttributeName();
            this.getServletContext().setAttribute(attrName, wac);
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Published WebApplicationContext of servlet '" + this.getServletName() + "' as ServletContext attribute with name [" + attrName + "]");
            }
        }

        return wac;
    }

initWebApplicationContext()做了三件事:

  1. 获取spring的根容器rootContext。
  2. 设置webApplicationContext,并按情况调用onRefresh()。
  3. 将webApplicationContext设置到ServletContext。

 

 

DispatcherServlet

 

 

 

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部