Spring MVC源码解析
Spring MVC 零XML配置原理
Spring MVC的核心是DispatcherServlet调度器,可以拦截所有的请求,然后按照Spring MVC的设计,分发、调度这些请求,是Spring MVC的入口。这个调度器本来是要用XML文件配置的,但是开发团队添加了用代码来替代的功能。
public class MyWebApplicationInitializer implements WebApplicationInitializer {
//参数是Web容器的上下文对象,里面应该是包含了所有的东西,可以利用这个对象来注册Web组件(如:filter、servlet、listener等)
@Override
public void onStartup(ServletContext servletCxt) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
//这个AppConfig类是自己写的配置类。关于Bean的配置,包扫描的配置都在这个AppConfig类上进行。
//如果你想要在配置类上配置Spring MVC,可以继承 WebMvcConfigurationSupport 类。
ac.register(AppConfig.class);
ac.refresh();
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
上面是替代XML配置的Java代码。自定义一个实现 WebApplicationInitializer 接口的类,Web容器(如Tomcat)会自动的调用此接口中的onStartup方法。利用此机制,在自定义的类中的onStartup方法中进行配置。
那么问题来了,为什么Web容器要调用这个onStartup方法呢?这是servlet3.0(不是Web容器哦)之后使用SPI机制的新规范。
什么?SPI?如果你的项目需要在Web容器启动的时候做一些事情,那么你可以在项目根目录的MATA-INF/services/目录下建立一个文件,名为:javax.servlet.ServletContainerInitializer,在这个文件里面写你要用到的类(这个类要实现servlet的一个接口),然后servlet会自动的调用你写到文件里面的类。
如上所述,如果你只用到了servlet,那么需要建立文件啥的。但是如果你用到了spring,那么建立文件的事spring已经帮你做了,只需要在spring提供的 WebApplicationInitializer 接口下做事就行了。
Spring MVC源码分析
发送一条HTTP请求。
- DispatcherServlet类,其中有doDispatch方法,在此方法中对请求进行初步处理(检查有没有文件),分发等工作。那么如何把一个请求分发到正确的Controller上呢?
Spring MVC寻找Controller的流程:
1)、扫描整个项目(Spring已经扫描了,把项目中各种注解的类都有记录在案,定义一个Map)。
2)、拿到所有加了@Controller注解的类。
3)、遍历所有类中的方法,判断方法上是否有@RequestMapping注解。
4)、将上一步找到的@RequestMapping注解中的value值和对应的方法对象,作为键值对放入定义好的Map。
5)、根据用户发送的请求URI,找到URI对应的方法对象。
Spring MVC寻找Controller的源码:
doDispatch方法中的getHandler方法是源码中匹配URI的方法,在getHandler中,利用handlerMapping这个工具类做匹配(有多重方式定义一个Controller,在匹配器的源码中有体现这一点,不同方式定义的Controller存储在不同的Map中)。
接下来有HandlerAdapter适配器来判断是那种类型的Controller(一种注解方式,两种实现接口的方式),不同类型的Controller调用的方式不同,常用的注解型Controller要用反射来调用其中的方法,实现接口类型的Controller可以直接调用实现类。
实现接口的类型,调用时可以用对象实例直接调用接口中的方法。
注解类型调用时比较复杂,首先是传参问题,Spring MVC中,参数是可以自动包装的,如果是字符串,会自动在请求中找参数名,如果是对象,会用反射填充属性等等。这个功能就是在这时候做的,Spring设计了一个参数处理器,会根据不同的参数类型,让不同的参数处理器来处理,最后会产生一个可以直接让反射使用的参数数组。这个参数处理器,Spring提供了自定义的方法(实现HandlerMethodArgumentResolver接口,然后在配置中新增这个参数处理器)。
Spring Boot源码解析
@SpringBootApplication注解
- @SpringBootConfiguration,标识某个类是Spring配置类,等价于@Configuration注解。
- @EnableAutoConfiguration,核心注解,里面有 @AutoConfigurationPackage注解,取代了@ComponentScan注解,功能是扫描带有当前注解的类同级目录和下级所有的目录(这就是为什么要把包建在Application类相同的文件夹了);还有 @Import 注解,导入了一个AutoConfigurationImportSelector的类,此类中有Spring Boot自动配置的核心代码。
AutoConfigurationImportSelector类
这里面有个selectImports方法,返回值是一个字符串数组,数组中的字符串必须是类名,Spring会根据这些类名用反射加载这些类。这是Spring技术的一个核心方法。 结合JavaConfig技术(Spring为市面上的许多框架都提供了Config类),Spring会在启动的时候,加载自己提供的Config类,也就是实现了自动配置。
具体实现就是在selectImports方法中,扫描Spring-Boot-AutoConfig项目中,MATA-INF目录下的spring.factories文件,里面有spring支持的所有框架的Config类的类名,正好就是selectImports方法要求的返回值。(PS:自己在自己的项目中写的spring.factories文件也会被扫描到,这意味着自己的框架也可以主动整合到SpringBoot中。)
本文深入探讨SpringMVC的零XML配置原理及源码分析,详细讲解DispatcherServlet的作用与配置,以及SpringMVC如何寻找Controller。同时,解析SpringBoot的@SpringBootApplication注解,揭示其自动配置的核心机制。

被折叠的 条评论
为什么被折叠?



