从SpringMVC到Spring Boot

1理解SpringMVC的流程

Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图
在这里插入图片描述
启动流程如下

  1. 当服务器启动时,会先加载web.xml,之后通过引入核心配置文件加载SpringMvc-servlet.xml,就会解析该xml配置文件

  2. 当解析到包扫描的时候,会扫描指定的包,并将含有@Controller注解类解析为处理器

  3. 如果配置过<mvc:annotation-driven/>就会解析Spring-MVC注解

  4. 解析@RequestMapping(value="/hello.action"),将指定的地址和当前方法的映射关系进行保存

  5. 用户发送请求至前端控制器DispatcherServlet。

  6. DispatcherServlet收到请求调用HandlerMapping处理器映射器。

  7. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

  8. DispatcherServlet调用HandlerAdapter处理器适配器。

  9. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

  10. Controller执行完成返回ModelAndView。

  11. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

  12. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

  13. ViewReslover解析后返回具体View。

  14. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

  15. DispatcherServlet响应用户。


2 理解 Spring Boot的流程

Spring 框架是通过 IOC 机制来管理 Bean 的。Spring Boot 依赖 Spring 框架来管理对象的依赖。Spring Boot 去除了大量的 xml 配置文件,简化了复杂的依赖管理,配合各种 starter 使用,基本上可以做到自动化配置。 用最简练的语言概括就是 Spring Boot 是基于Spring
的一套快速开发整合包。

在这里插入图片描述

springboot中只需要有@SpringBootApplication这个注解,有了它马上就能够让整个应用跑起来。实际上它只是一个组合注解,@Configuration配置类,@ComponentScan类,包扫描,@EnableAutoConfiguration根据需求自动加载相关的bean这三个注解。

@Configuration
public class MockConfiguration{
    //bean定义 其返回值将作为一个bean定义注册到Spring的IoC容器,
    //方法名将默认成该bean定义的id。
    @Bean
    public MockService mockService(){
        return new MockServiceImpl();
    }
}
@ComponentScan
// 我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围
//自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。
//这个这个注解尤为重要 
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

//借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器
//在配置系统初始化的时候用
public abstract class SpringFactoriesLoader {
    //loadSpringFactories方法直接加载所有的META-INF/spring.factories文件内容
    public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
        ...
    }


    public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        ....
    }
}
/*配合@EnableAutoConfiguration使用的话 根据EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类
*从classpath中搜寻所有的META-INF/spring.factories配置文件,
*并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)
*实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,
*然后汇总为一个并加载到IoC容器。
*/

在这里插入图片描述

启动流程如下
第一个步骤是构造一个SpringApplication应用

  1. 装配参数和环境,据classpath里面是否存在某个特征类ConfigurableWebApplicationContext, 来决定是否应该创建一个为Web应用使用的ApplicationContext类型,确定是web环境还是非web环境。
  2. 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer
  3. 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener
  4. 推断并设置main方法的定义类。

第二个步骤是run SpringApplication

  1. 遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。注册监听器和初始器后,开始调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。
  2. 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
  3. 获取上下文得到环境信息之后,遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。
  4. 如果SpringApplication的showBanner属性被设置为true,则打印banner。
  5. 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
  6. ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
  7. bean的定义信息加载完成,遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
  8. 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
  9. 遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
  10. 调用ApplicationContext的refresh()方法,装配context beanfactory等非常重要的核心组件,完成IoC容器可用的最后一道工序。
  11. 查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
  12. 所有bean初始化完毕,所有回调处理完成,发布ApplicationReadyEvent事件,启动完毕,表示服务已经可以开始正常提供服务了。通常我们这里会监听这个事件来打印一些监控性质的日志,表示应用正常启动了。

在这里插入图片描述
启动信息如下:

第 9 行,启动SampleController。

第10行,查找active profile,无,设为default。

第11行,刷新上下文。

第12行,初始化tomcat,设置端口8080,设置访问方式为http。

第13行,启动tomcat服务。

第14行,启动Servlet引擎。

第15行,Spring内嵌的WebApplicationContext 初始化开始。

第16行,Spring内嵌的WebApplicationContext 初始化完成。

第17行,映射servlet,将 dispatcherServlet 映射到 [/] 。

第18行,映射filter,将 characterEncodingFilter 映射到 [/*] 。

第19行,映射filter,将 hiddenHttpMethodFilter 映射到 [/*] 。

第20行,映射filter,将 httpPutFormContentFilter 映射到 [/*] 。

第21行,映射filter,将 requestContextFilter 映射到 [/*] 。

第22行,查找 @ControllerAdvice。

第23行,映射路径 “{[/]}” 到 cn.larry.spring.controller.SampleController.home()。

第24行,映射路径 “{[/error]}” 到 org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)。

第25行,映射路径 “{[/error],produces=[text/html]}” 到 org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)。

第30行,tomcat启动完毕。

第31行,SampleController启动耗费的时间。

第32行,初始化 dispatcherServlet 。

第33行,dispatcherServlet 的初始化已启动。

第34行,dispatcherServlet 的初始化已完成。

第35行,收到shutdown关闭请求。

第36行,关闭AnnotationConfigEmbeddedWebApplicationContext。

参考:
SpringMVC工作原理 及注解说明
Spring Boot干货系列:(三)启动原理解析


版权声明:本文为u010020726原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。