前言 如果这是你第二次看到师长,说明你在觊觎我的美色! 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 专车介绍 该趟专车是开往Spring Boot请求处理源码分析专车,主要用来分析Spring Boot是如何将我们的请求路由到指定的控制器方法以及调用执行。 专车问题 为什么我们在控制器中添加一个方法,使用@RequestMapping注解标注,指定一个路径,就可以用来处理一个web请求? 如果多个方法的请求路径一致,Spring Boot是如何处理的? 专车示例 @RestController @RequestMapping("/persons") public class PersonController { private static List personList = new ArrayList<>(); static { personList.add(new Person(10001, "test1")); personList.add(new Person(10002, "test2")); personList.add(new Person(10003, "test3")); personList.add(new Person(10004, "test4")); personList.add(new Person(10005, "test5")); } @GetMapping("/") public List list() { return personList; } @GetMapping("/{id}") public Person get(@PathVariable("id") Integer id) { Person defaultPerson = new Person(88888, "default"); return personList.stream().filter(person -> Objects.equals(person.getId(), id)).findFirst().orElse(defaultPerson); } @PostMapping("/") public void add(@RequestBody Person person) { personList.add(person); } @PutMapping("/") public void update(@RequestBody Person person) { personList.removeIf(p -> Objects.equals(p.getId(), person.getId())); personList.add(person); } } 示例代码提供了GET、POST、PUT请求,接下里我们会结合示例进行源码分析 专车分析 此次分析主要从2个大的方面进行分析:请求初始化、请求处理 请求初始化 请求流程 一次完成的请求流程就是请求--->处理--->响应,业务逻辑处理最终交由我们创建的Servlet来进行处理。以前在使用Spring MVC框架的时候,我们都会在web.xml中配置一个DispathcherServlet。接下来就让我们来看看DispathcherServlet的类图 从如上图可以清晰的看到DispatcherServlet的继承关系。其中一个名为HttpServlet的类,如果写过Servlet的应该都比较的熟悉,以往基于Servlet开发,都会创建一个Servlet实现类,继承HttpServlet并重写service方法,最后在web.xml中配置我们我们创建的Servlet实现类,这样我们就可以使用创建的Servlet实现类来处理我们的web请求了。 HttpServlet初始化 在我们第一次请求的时候会进行Servlet的初始化,主要用来初始化资源。HttpServlet的init方法由父类GenericServlet声明,由子类HttpServletBean实现。 初始化方法:HttpServletBean#init @Override public final void init() throws ServletException { // ...省略部分代码 // Let subclasses do whatever initialization they like. // 暴露出去一个方法,可以让子类初始化一些自己想要初始化的内容 initServletBean(); } 创建WebApplicationContext:FrameworkServlet#initServletBean @Override protected final void initServletBean() throws ServletException { // ...省略部分代码 try { // 初始化WebApplicationContext对象 this.webApplicationContext = initWebApplicationContext(); // 空实现 initFrameworkServlet(); } // ...省略部分代码 } 初始化WebApplicationContext对象:FrameworkServlet#initWebApplicationContext protected WebApplicationContext initWebApplicationContext() { // 获取WebApplicationContext对象 WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; // ... 省略部分代码 if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. synchronized (this.onRefreshMonitor) { // 刷新资源 onRefresh(wac); } } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; } 刷新资源:DispatcherServlet#onRefresh @Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } 初始化策略:DispatcherServlet#initStrategies protected void initStrategies(ApplicationContext context) { // 初始化多文件解析器 initMultipartResolver(context); // 初始化本地化解析器 initLocaleResolver(context); // 初始化主题解析器 initThemeResolver(context); // 初始化HandlerMapping initHandlerMappings(context); // 初始化HandlerAdapter initHandlerAdapters(context); // 初始化异常解析器 initHandlerExceptionResolvers(context); // 初始化请求到视图名称翻译器 initRequestToViewNameTranslator(context); // 初始化视图解析器 initViewResolvers(context); initFlashMapManager(context); } 来看一下初始化HandlerMapping实现:DispatcherServlet#initHandlerMappings private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. // 从IOC容器中获取类型为HandlerMapping的bean // 对应的bean有RequestMappingHandlerMapping、SimpleUrlHandlerMapping、WelcomePageHandlerMapping Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); // We keep HandlerMappings in sorted order. // 对HandlerMapping进行排序 AnnotationAwareOrderComparator.sort(this.handlerMappings); } } } 通过对初始化HandlerMapping实现的分析,我们可以得出,所有的初始化操作就是从IOC容器中获取相应类型的Bean,然后进行属性赋值。 既然能从IOC容器中获取到HandlerMapping bean,那么一定存在定义bean 的地方。打开WebMvcAutoConfiguration类,可以看到如下代码 /** * Configuration equivalent to {@code @EnableWebMvc}. * 此配置等同于使用@EnableWebMvc注解 */ @Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { private final WebMvcProperties mvcProperties; private final ListableBeanFactory beanFactory; private final WebMvcRegistrations mvcRegistrations; public EnableWebMvcConfiguration( ObjectProvider mvcPropertiesProvider, ObjectProvider mvcRegistrationsProvider, ListableBeanFactory beanFactory) { this.mvcProperties = mvcPropertiesProvider.getIfAvailable(); this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique(); this.beanFactory = beanFactory; } // 声明RequestMappingHandlerAdapter bean @Bean @Override public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(); adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect()); return adapter; } // 声明RequestMappingHandlerMapping bean @Bean @Primary @Override public RequestMappingHandlerMapping requestMappingHandlerMapping() { // Must be @Primary for MvcUriComponentsBuilder to work return super.requestMappingHandlerMapping(); } } 在如上代码中可以看到HandlerAdapter和HandlerMapping bean的声明 创建RequestMappingHandlerMapping @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { // 创建RequestMappingHandlerMapping对象 RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping(); // 设置属性 mapping.setOrder(0); // 设置拦截器 mapping.setInterceptors(getInterceptors()); mapping.setContentNegotiationManager(mvcContentNegotiationManager()); mapping.setCorsConfigurations(getCorsConfigurations()); // ...省略部分代码 return mapping; } 可以看到除了创建RequestMappingHandlerMapping对象,其它的都是设置属性信息,接下来重点分析创建对象部分的代码 WebMvcConfigurationSupport#createRequestMappingHandlerMapping protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { return new RequestMappingHandlerMapping(); } 可以创建RequestMappingHandlerMapping对象的代码很简单,就是调用了无参数构造进行初始化。但是通过查看RequestMappingHandlerMapping的继承关系,我们可以看到该类实现了InitializingBean接口,这也就告诉我们当看到很简单的代码的时候,我们就要看看类的继承关系,来看看是否使用其他形式进行逻辑实现。 既然实现了InitializingBean接口,那就看看创建bean后的初始化方法afterPropertiesSet @Override public void afterPropertiesSet() { this.config = new RequestMappingInfo.BuilderConfiguration(); this.config.setUrlPathHelper(getUrlPathHelper()); this.config.setPathMatcher(getPathMatcher()); this.config.setSuffixPatternMatch(this.useSuffixPatternMatch); this.config.setTrailingSlashMatch(this.useTrailingSlashMatch); this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch); this.config.setContentNegotiationManager(getContentNegotiationManager()); // 调用父类的初始化方法 super.afterPropertiesSet(); } @Override **public** **void** **afterPropertiesSet**() { // 初始化处理方法 initHandlerMethods(); } 初始化处理方法:AbstractHandlerMethodMapping#initHandlerMethods protected void initHandlerMethods() { // 获取并遍历候选bean名称,候选bean就是从IOC容器中获取类型为Object的bean名称,也就是所有的Bean名称 for (String beanName : getCandidateBeanNames()) { // 如果bean的名称不以“scopedTarget.”开头,才进行处理 if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { // 处理候选bean名称 processCandidateBean(beanName); } } handlerMethodsInitialized(getHandlerMethods()); } 处理候选bean名称:AbstractHandlerMethodMapping#processCandidateBean protected void processCandidateBean(String beanName) { Class beanType = null; try { // 根据bean的名称获取对应bean的类型 beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isTraceEnabled()) { logger.trace("Could not resolve type for bean '" + beanName + "'", ex); } } // 如果bean的类型不为空并且对应类上含有@Controller注解或者@RequestMapping注解 if (beanType != null && isHandler(beanType)) { // 推断处理方法 detectHandlerMethods(beanName); } } 推断处理方法:AbstractHandlerMethodMapping#detectHandlerMethods protected void detectHandlerMethods(Object handler) { // 根据bean名称获取类型 Class handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { Class userType = ClassUtils.getUserClass(handlerType); // 获取处理方法 Map methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup) method -> { try { // selectMethods方法获取当前类中所有的方法,针对PersonController类就有list、get、add、update四个方法,遍历这四个方法,分别创建对应的RequestMappingInfo对象 // 根据method获取RequestMappingInfo对象 return getMappingForMethod(method, userType); } }); if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); }); } } 根据method获取RequestMappingInfo对象:RequestMappingHandlerMapping#getMappingForMethod @Override @Nullable protected RequestMappingInfo getMappingForMethod(Method method, Class handlerType) { // 根据method对象创建RequestMappingInfo对象 RequestMappingInfo info = createRequestMappingInfo(method); if (info != null) { // 如果当前方法所在的类也含有@RequestMapping对象,那么也创建一个RequestMappingInfo对象 RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); if (typeInfo != null) { // 将两个RequestMappingInfo对象进行合并,比如我们PersonController上指定@RequestMapping("/persons"),针对list方法,list方法上指定@RequestMapping("/"),那么合并后的映射路径就是/persons/ info = typeInfo.combine(info); } String prefix = getPathPrefix(handlerType); if (prefix != null) { info = RequestMappingInfo.paths(prefix).build().combine(info); } } // 返回RequestMappingInfo对象 return info; } 回到推断处理方法中:AbstractHandlerMethodMapping#detectHandlerMethods protected void detectHandlerMethods(Object handler) { // 根据bean名称获取类型 Class handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { Class userType = ClassUtils.getUserClass(handlerType); // 获取处理方法,每个方法都有对应的RequestMappingInfo对象 Map methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup) method -> { try { // selectMethods方法中当前类中所有的方法,针对PersonController类就有list、get、add、update四个方法,遍历这四个方法,分别创建对应的RequestMappingInfo对象 // 根据method获取RequestMappingInfo对象 return getMappingForMethod(method, userType); } }); if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } // 遍历处理方法 methods.forEach((method, mapping) -> { // 获取可以执行的method对象 Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); // 注册处理方法 registerHandlerMethod(handler, invocableMethod, mapping); }); } } 注册处理方法:AbstractHandlerMethodMapping.MappingRegistry#register public void register(T mapping, Object handler, Method method) { // 加写锁,加锁是因为我们可以在代码中手动注册处理方法,为了防止并发问题,此处需要加锁处理 this.readWriteLock.writeLock().lock(); try { // 创建HandlerMethod对象 HandlerMethod handlerMethod = createHandlerMethod(handler, method); assertUniqueMethodMapping(handlerMethod, mapping); // 将RequestMappingInfo对象和HandlerMethod对象添加到map集合中 this.mappingLookup.put(mapping, handlerMethod); List directUrls = getDirectUrl