03.SpringMVC之器

时间:2019-09-09
本文章向大家介绍03.SpringMVC之器,主要包括03.SpringMVC之器使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

整体结构介绍

在Servlet的继承结构中一共有5个类,GenericServlet和HttpServlet在java中剩下的三个类HttpServletBean、FrameworkServlet和DispatcherServlet是SpringMVC中的这三个类直接实现三个接口:EnvironmentCapable、EnvironmentAware和ApplicationContextAware。
XXXAware在spring里表示对XXX可以感知,通俗点解释就是:如果在某个类里面想要使用spring的一些东西,就可以通过实现XXXAware接口告诉spring,spring看到后就会给你送过来,而接收的方式是通过实现接口唯一的方法setXXX,比如,有一个类想要使用当前的ApplicationContext,那么我们只需要让它实现ApplicationContextAware接口,然后实现接口中唯一的方法,void setApplicationContext(ApplicationContext applicationContext(会自动传过来,直接用))就可以了,spring会自动调用这个方法将applicationContext传给我们,我们只需要接收就可以了。
EnvironmentCapable,顾名思义,当然就是具有Environment的能力,也就是可以提供Environment,所以EnvironmentCapable唯一的方法是Environment getEnvironment(),用于实现EnvironmentCapable接口的类,就是告诉spring它可以提供Environment,当spring需要Environment的时候就会调用其getEnvironment方法跟它要

HttpServletBean

在HttpServletBean的init方法中,首先将Servlet中配置的参数使用BeanWrapper设置到DispatcherServlet的相关属性,然后调用模板方法initServletBean,子类就通过这个方法初始化

public final void init() throws ServletException {
    // 1. 操作配置文件里的属性 
    PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(),this.requiredProperties);
 
    if (!pvs.isEmpty()) {
        try {
            // 2.获取目标对象的beanwrapper对象
            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) {
                throw ex;
            }
           }
    // 空方法 让子类实现
    initServletBean();
}

BeanWrapper是Spring 提供的一个用来操作JavaBean属性的工具,使用它可以直接修改一个对象的属性

public class User{
    String userName;
    //省略get和set方法
}
public class BeanWrapperTest{
    psvm{
        User user = new User();
        BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(user);
        bw.setPropertyValue("userName","张三");
        sout(user.getUserName());
        PropertyValue value = new PropertyValue("userName","李四");
        sout(user.getUserName());
    }
}

FrameworkServlet

FrameworkServlet继承HttpServletBean,FrameworkServlet的初始化入口方法是initServletBean

// org.springframework.web.servlet.FrameworkServlet
protected final void initServletBean() throws ServletException{
    //初始化WebApplicationContext
    this.webApplicationContext = initWebApplicationContext();
    //模板方法,子类可以覆盖在里面做一些初始化的工作
    initFrameworkServlet();
}

protected WebApplicationContext initWebApplicationContext(){
    //获取rootContext
    WebApplicationContext rootContext = WebApplicationContextUtils.getApplictionContext(getServletContext());
    WebApplicationContext  wac = null;
    //如果已经通过构造方法设置了webApplicationContext
    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);
                }
                configureAndRefreshWebApplicationContext(cwac)
            }
        }
    }
    if(wac == null){
        //当webApplicationContext已经存在ServletContext中时,通过配置在Servlet中的contextAttribute参数获取
        wac = findWebApplicationContext();
    }
    if(wac == null)[
        //如果webApplicationContext还没有创建,则创建一个
        wac = createWebApplicationContext(rootContext);
    }
    if(!this.refreshEventReceived){
        //当ContextRefreshedEvent事件没有触发时调用此方法,模板方法,可以在子类重写
        onRefresh(wac);
    }
    if(this.publicContext){
        //将ApplicationContext保存到ServletContext中
        String attrName = getServletContextAttributeName();
        getServletContext().setAttribute(attrName,wac);
    }
    return wac;
}

这个initWebApplicationContext方法做了三件事

1.获取spring的根容器rootContext

获取根容器的原理是,默认情况下spring会将自己的容器设置成ServletContext属性,默认根容器的key为org.springframework.web.context.WebApplicationContext.ROOT,所以获取根容器只需要调用ServletContext的getAttribute就可以了

2.设置webApplicationContext并根据情况调用onRefresh方法
3.将webApplicationContext设置到ServletContext中

DispatcherServlet

OnRefresh方法是DispathcerServlet的入口方法,OnRefresh中简单地调用了initStrategis,在initStrategies中调用了9个初始化方法

//org.springframework.web.servlet.DispatcherServlet
protected void onRefresh (ApplicationContext context){
    initStrategies(context);
}

protected void initStrategies(Application context){
    initMultipartResolver(context);
    initLocalResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

原文地址:https://www.cnblogs.com/deityjian/p/11494345.html