一.Spring运行原理
1.相关组件
前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU。
处理器映射器(HandlerMapping):根据URL去查找处理器
处理器(Handler):(需要程序员去写代码处理逻辑的)
处理器适配器(HandlerAdapter):会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用)
视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面
二.源码分析
DispatcherServlet
1.HttpServletBean
@Override
public final void init() throws ServletException {
... ...
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);
}
... ...
initServletBean();
}
DispatcherServlet 的 init() 方法在其父类 HttpServletBean 中实现的,它覆盖了 GenericServlet 的 init() 方法,主要作用是加载 web.xml 中 DispatcherServlet 的
在 HttpServletBean 的 init() 方法中调用了 initServletBean() 这个方法,它是在 FrameworkServlet 类中实现的,主要作用是建立 WebApplicationContext 容器(有时也称上下文),并加载 SpringMVC 配置文件中定义的 Bean 到改容器中,最后将该容器添加到 ServletContext 中。
2.FrameworkServlet
protected final void initServletBean() throws ServletException {
... ...
long startTime = System.currentTimeMillis();
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
... ...
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
... ...
}
if (wac == null) {
wac = findWebApplicationContext();
}
if (wac == null) {
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
onRefresh(wac); // point
}
return wac;
}
WebApplicationContext 继承于 ApplicationContext 接口,从容器中可以获取当前应用程序环境信息,它也是 SpringMVC 的 IOC 容器。
建立好 WebApplicationContext(上下文) 后,通过 onRefresh(ApplicationContext context) 方法回调,进入 DispatcherServlet 类中。onRefresh() 方法,提供 SpringMVC 的初始化。
3.DispatcherServlet
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
在 initStrategies() 方法中进行了各个组件的初始化。
二.当有请求发送过来
HttpServlet 提供了 doGet()、doPost() 等方法,DispatcherServlet 中这些方法是在其父类 FrameworkServlet 中实现的。doGet()、doPost()又都调用了 processRequest() 方法
FrameworkServlet
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
... ...
// 由 DispatcherServlet 实现
doService(request, response);
... ...
}
DispatcherServlet
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
... ...
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
doDispatch(request, response); //ponit
}
... ...
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);.
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
... ...
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
... ...
}
DispatcherServlet 的 doService() 方法主要是设置一些 request 属性,并调用 doDispatch() 方法进行请求分发处理,doDispatch() 方法的主要过程是通过 HandlerMapping 获取 Handler,再找到用于执行它的 HandlerAdapter,执行 Handler 后得到 ModelAndView ,ModelAndView 是连接“业务逻辑层”与“视图展示层”的桥梁,接下来就要通过 ModelAndView 获得 View,再通过它的 Model 对 View 进行渲染