1理解SpringMVC的流程
Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图
启动流程如下
当服务器启动时,会先加载web.xml,之后通过引入核心配置文件加载SpringMvc-servlet.xml,就会解析该xml配置文件
当解析到包扫描的时候,会扫描指定的包,并将含有@Controller注解类解析为处理器
如果配置过<mvc:annotation-driven/>就会解析Spring-MVC注解
解析@RequestMapping(value="/hello.action"),将指定的地址和当前方法的映射关系进行保存
用户发送请求至前端控制器DispatcherServlet。
DispatcherServlet收到请求调用HandlerMapping处理器映射器。
处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
DispatcherServlet调用HandlerAdapter处理器适配器。
HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
Controller执行完成返回ModelAndView。
HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
ViewReslover解析后返回具体View。
DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
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应用
- 装配参数和环境,据classpath里面是否存在某个特征类ConfigurableWebApplicationContext, 来决定是否应该创建一个为Web应用使用的
ApplicationContext类型,确定是web环境还是非web环境。 - 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的
ApplicationContextInitializer。 - 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的
ApplicationListener。 - 推断并设置main方法的定义类。
第二个步骤是run SpringApplication
- 遍历执行所有通过
SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。注册监听器和初始器后,开始调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。 - 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
- 获取上下文得到环境信息之后,遍历调用所有SpringApplicationRunListener的
environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。 - 如果SpringApplication的showBanner属性被设置为true,则打印banner。
- 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
- ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
- bean的定义信息加载完成,遍历调用所有SpringApplicationRunListener的
contextPrepared()方法。 - 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
- 遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
- 调用ApplicationContext的refresh()方法,装配context beanfactory等非常重要的核心组件,完成IoC容器可用的最后一道工序。
- 查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
- 所有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。