spring MVC自身的创建
1.整体结构介绍
springMVC中核心servlet的继承结构:
从结构图中可以看到,servlet的继承结构中一共有5个类。这里来说一下spring中的三个类。
这三个类直接实现三个接口:EnvironmentCapable、EnvironmentAware和Application-ContextAware。XXXAware在spring里表示对XXX可以感知,通俗点解释就是:如果在某个类里面想要使用spring的一些东西,就可以通过实现XXXAware接口告诉spring,spring看到后就会给你送过来,而接收的方式是通过实现接口唯一的方法set-XXX。
比如,有一个类想要使用当前的ApplicationContext,那么我们只需要让它实现ApplicationContextAware接口,然后实现接口中唯一的方法void setApplicationContext(ApplicationContext applicationContext)就可以了,spring会自动调用这个方法将applicationContext传给我们,我们只需要接收就可以了。EnvironmentCapable,顾名思义,当然就是具有Environment的能力,也就是可以提供Environment,所以EnvironmentCapable唯一的方法是Environment getEnvironment(),用于实现EnvironmentCapable接口的类,就是告诉spring它可以提供Environment,当spring需要Environment的时候就会调用其getEnvironment方法跟它要。
了解了Aware和Capable的意思,下面再来看一下ApplicationContext和Environment。前者相信大家都很熟悉了,后者是环境的意思。实际上在HttpServletBean中Environment使用的是Standard-Servlet-Environment(在createEnvironment方法中创建),这里封装了ServletContext,同时还封装了ServletConfig、JndiProperty、系统环境变量和系统属性,这些都封装到了其propertySources属性下。
为了让大家理解得更深刻,在前面项目的GoController中获取Environment,然后通过调试看一下。首先让GoController实现EnvironmentAware接口,这样spring就会将Environment传给我们,然后在处理请求的方法中加入断点,这样就可以查看spring传进来的内容了。
2.HttpServletBeen
我们知道Servlet创建时可以直接调用无参数的init方法。HttpServletBean的init方法如下:
可以看到,在HttpServletBean的init中,首先将Servlet中配置的参数使用BeanWrapper设置到DispatcherServle的相关属性,然后调用模板方法initServletBean,子类就通过这个方法初始化。
BeanWrapper:BeanWrapper是Spring提供的一个用来操作JavaBean属性的工具,使用它可以直接修改一个对象的属性。
public class User { private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
import org.springframework.beans.BeanWrapper; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.beans.PropertyValue; import com.excelib.common.User; public class BeanWrapperTest { public static void main(String[] args) { User user=new User(); BeanWrapper bw=PropertyAccessorFactory.forBeanPropertyAccess(user); bw.setPropertyValue("userName","张安"); System.out.println(user.getUserName()); PropertyValue prvalue=new PropertyValue("userName", "六六"); bw.setPropertyValue(prvalue); System.out.println(user.getUserName()); } }
这个例子首先新建了一个User对象,其次使用PropertyAccessorFactory封装成Bean-Wrapper对象,这样就可以使用了。
3.FrameworkServlet
首先看源码:他继承了httpservletBean,实现了ApplicationContextAware
他的初始化入口:
这里可以查看initWebApplicationContext()源码,他主要做了三件事。
①获取spring的根容器rootContext
②设置webApplicationContext并根据情况调用onrefresh()
③讲webApplicatiuonContext设置到servletContest中
4.DispatcherServlet
有兴趣的可以研究一下 源码。
5.总结
通过源码,了解Spring MVC自身的创建过程,Spring MVC中Servlet一共有三个层次,分别是HttpServletBean、FrameworkServlet和DispatcherServlet。HttpServletBean直接继承自Java的HttpServlet,其作用是将Servlet中配置的参数设置到相应的属性;FrameworkServlet初始化了WebApplicationContext,DispatcherServlet初始化了自身的9个组件。
FrameworkServlet初始化WebApplicationContext一共有三种方式,过程中使用了Servlet中配置的一些参数。
整体结构非常简单——分三个层次做了三件事,但具体实现过程还是有点复杂的。这其实也是spring的特点:结构简单,实现复杂。结构简单主要是顶层设计好,实现复杂的主要是提供的功能比较多,可配置的地方也非常多。当然,正是因为实现复杂,才让Spring MVC使用起来更加灵活,这一点在后面会有更深刻的体会。自己需要静下心来对照着源代码耐心地去看,我现在还有很多地方不是很明白,不在实际操作上应用不会了解很透彻,希望读者可以多留言交流。