美文网首页
servletContext在spring中如何初始化(一)

servletContext在spring中如何初始化(一)

作者: guessguess | 来源:发表于2020-06-29 11:33 被阅读0次

先来看看传统项目中,springMVC如何搭建。

1.web项目中,总有一个web.xml。如图所示,需要指定最终处理请求的Servlet,以及一些初始化的参数,指定配置文件在哪里。那么如何载入容器的相关信息。

web.xml中,Servlet的指定

2.我们先来看看一些结构。关于DisPatcherServlet类的。

Dispatcher类的结构

上图就可以解释,如何将web.xml中Servlet相关信息载入容器的。通过抽象类GenericServlet中的init(ServletConfigc onfig)方法。我们来看看这个方法的实现。如下图所示。

GenericServlet中init(config)方法的实现

看到init(ServletConfig config)方法的注释,这个config包含了Servlet的相关配置信息,此外这个方法的实现将这个config保存起来,方便后期使用。init(ServletConfig config)中除了将config保存起来,下一步便是初始化了。在这个类中,init方法是空方法,如下图所示。

GenericServlet中init()方法的实现

看一下注解,这个方法的话,直接覆写就可以了,就用不着去调用super.init(config),想了一下这是一种很聪明的做法,各个不同的servlet实现类只需要覆写init()方法即可。然后通过父类去调用init(Config)方法即可,而不用去关心各个子类的init方法的具体实现。

下面进入重点,那么DispatcherServlet究竟对init()方法做了什么实现呢,在源码中,DispatcherServlet并没有实现对应的方法,随后发现对应的父类FrameworkServlet也没有,最终FrameworkServlet的父类HttpServletBean实现了init()方法。

话不多说,直接贴代码·。

init()方法的具体实现,位于HttpServletBean类中。

首先当我看到这段代码的时候,我是很一脸懵逼的,但是我还是决定硬着头皮来解析这段代码,看到那么多的新结构,首先来对结构进行拆分把。本文标题里面的第x行,指的是上图的第x行。

从init()第154行讲起

PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);

先看看具体的结构。

PropertyValues的具体结构

下面来看看构造方法如何实现的。为了后续做准备,楼主先把web.xml中的文件修改一下,添加了一个自定义参数,如下图所示

添加自定义参数后的web.xml文件

ServletConfigPropertyValues的构造方法,如下图所示

ServletConfigPropertyValues构造方法的实现

看代码太抽象了点,我们来debug一下吧。

这是debug出来的结果,[contextConfigLocation=classpath:spring/servlet-context.xml, testParam=ojbk],此处便是将web.xml中的<init-Param>的name,value转换为PropertyValue对象。随后保存到MutablePropertyValues类中的propertyValueList中去。requirementProperties应该就是我们自己定义必须存在的属性,若没有就会报错。

总结一下,第154行的作用,将web.xml中servlet的初始化方法注入到MutablePropertyValues的成员变量propertyValueList中去。下面讲一下第157行

第157行

BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);

先来看看BeanWrapper是什么鬼东西。

BeanWrapper的结构图。纯粹是一个接口

PropertyAccessorFactory又是什么鬼东西呢?

PropertyAccessorFactory是一个抽象类,用于返回一个BeanWrapper

下面看看这个工厂方法的具体实现,内容很简单,就一句话

public static BeanWrapper forBeanPropertyAccess(Object target) {

      return new BeanWrapperImpl(target);

}

好,那么问题又来了,BeanWrapperImpl又是什么鬼东西。看看下面的结构图,其实往上还有很多层接口,但是没必要贴出来了,主要是分析的是AbstractNestablePropertyAccessor的构造方法。因为new BeanWrapperImpl(target)最终的调用其实是AbstractNestablePropertyAccessor类的构造方法。

BeanWrapperImpl的结构图 该构造方法的具体实现

第一个方法registerDefaultEditors()是在PropertyEditorRegistrySupport类中实现,将defaultEditorsActive改为true,此处过于简单,至于后面做什么用的再看。

再看第二个方法setWrappedInstance(Object obj),看了源码,其主要作用是对BeanWrapperImpl的父类(AbstractNestablePropertyAccessor)做一些成员变量的封装

setWrappedInstance(Object obj)的具体实现 TypeConverterDelgate构造方法

从上图可知,便是将生成的BeanWrapperImpl对象,以及httpServletBean对象注入到对应的成员变量中。注:BeanWrapperImpl为PropertyEditorRegistrySupport的子类。

总结一下BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);最终生成了一个对象,该对象的成员变量中,包含了httpServletBean对象,bw.wrapperObject=httpServletBean。然后还有一个TypeConverterDelgate类型转换器的成员变量。现在还不知道有什么作用。后面再看看。

第158行

ResourceLoader resourceLoader=new ServletContextResourceLoader(getServletContext());

看到这个名字,相信大家都知道用于做什么了,资源加载器。先看看这个类的结构

ServletContextResourceLoader的结构图

其实说白了就是将servletContext注入到资源加载器这个对象里面去。看具体实现。

构造方法的具体实现

那么好了,如何拿到这个servletContext呢,我们来看一下getServletContext()这个方法。还记得通过抽象类GenericServlet中的init(ServletConfig config)这个方法吗,加载servlet配置的时候会将对应的servletConfig注入到GenericServlet的成员变量中去,通过这个方法我们可以拿到servletConfig,从而再拿到servletContext。

总结一下,这个方法是拿到servlet上下文,并且注入资源加载器。

第159行

bw.registerCustomEditor(Resource.classnew ResourceEditor(resourceLoader, getEnvironment()));

第157行说了那么多,总算要进入主题了。不然都不知道那个对象做什么用的。

先分别看看Resource.class以及ResourceEditor的结构

org.springframework.core.io.Resource这个类纯粹是一个接口,实现了部分的方法。不过多描述。

接下来看一下org.springframework.core.io.ResourceEditor的结构。

ResourceEditor的结构图

ResourceEditor中包含了俩个成员变量,resourceLoader,以及propertyResolver,先来看看构造方法吧

最终这个方法也是没有做什么,只是注入一些成员变量

bw.registerCustomEditor(Resource.classnew ResourceEditor(resourceLoader, getEnvironment()));那么getEnvironment()方法中返回的对象必然是PropertyResolver的子类。我们先来看看这个方法的实现。

getEnvironment()的代码实现

从代码上来看,没有便会new一个,此处也是将对应的对象注入成员变量罢了。

那么最后,我们看看registerCustomEditor(ClassrequiredType, PropertyEditorpropertyEditor);这个方法的实现吧。org.springframework.beans.BeanWrapperImpl.BeanWrapperImpl这个类一直往上推,最终找到继承的父类org.springframework.beans.PropertyEditorRegistrySupport实现了该方法。

registerCustomEditor方法实现

看了一下此代码,其实也是将一些变量进行保存。不做过多分析。将对应的Resource.class以及ResourceEditor放到对应的map(这个map是BeanWrapperImpl的一个父类的属性)里面去。可以猜想一下后期如何使用。

第160行

initBeanWrapper(bw);空方法,啥也没做

第161行

bw.setPropertyValues(pvs,true);

这个方法是由父类org.springframework.beans.AbstractPropertyAccessor实现的,可以看看前面的结构图。下面看看具体实现。

bw.setPropertyValues(pvs,true)的方法实现

第161行我是没看懂,先跳过

相关文章

网友评论

      本文标题:servletContext在spring中如何初始化(一)

      本文链接:https://www.haomeiwen.com/subject/axonyhtx.html