美文网首页spring
springMVC源码分析初始化过程

springMVC源码分析初始化过程

作者: loveFXX | 来源:发表于2019-11-21 22:20 被阅读0次

    springMVC初始化

    在分析具体的url请求之前,需要了解springMVC环境(spring的web容器)如何进行初始化的

    实例代码

    package com;
    @Configuration
    @ComponentScan("com.mvc")
    @EnableWebMvc
    public class AppConfig implements WebMvcConfigurer {
        //视图解析
        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            registry.jsp( "/app/",".html" );
        }
        //消息转换
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add( new FastJsonHttpMessageConverter() );
        }
    }
    
    
    package com.initializer;
    public class MyWebApplicationInitializer implements WebApplicationInitializer {
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            //初始化spring 容器
            AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
            ac.register( AppConfig.class);
            DispatcherServlet servlet = new DispatcherServlet(ac);
            ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
            registration.setLoadOnStartup(1);
            registration.addMapping("*.do");
        }
    }
    
    package com.mvc;
    @Component("/name.do") 
    public class BeanNameController implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("beanName---Controller");
            return null;
        }
    }
    
    package com.mvc;
    @Component("/name1.do") 
    public class HandleController implements HttpRequestHandler {
        @Override
        public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("beanname-------HttpRequestHandler");
        }
    }
    
    package com.mvc;
    @Controller
    public class TestController {
        @RequestMapping("/test.do")
        @ResponseBody                                                 
        public Object test(String name, HttpServletRequest request, HttpServletResponse response ){
            request.getParameter("name");
            Map hashMap = new HashMap();
            hashMap.put("key","value");
            return  hashMap;
        }
    
        @RequestMapping("/model.do")
        public String model(HttpServletRequest request,HttpServletResponse response){
            // /app/index.html
            return "index";
        }
    }
    

    debug分析

    springMVC初始化,是从tomcat初始化servlet开始。具体如何开始执行servlet需要tomcat源码。在这里只分析tomcat启动后初始化Servlet在springweb容器的实现流程,从HttpServletBean的init方法开始
    HttpServletBean的全路径是org.springframework.web.servlet.HttpServletBean (spring实现)
    HttpServlet的全路径是javax.servlet.http.HttpServlet (jdk)
    HttpServletBean继承了HttpServlet

    init

    HttpServletBean#init 初始化方法init


    init.png
    initServletBean

    FrameworkServlet#initServletBean 初始化ServletBean


    initServletBean.png
    initWebApplicationContext

    FrameworkServlet#initWebApplicationContext 初始化WebApplicationContext(web应用上下文---spring形式的web环境)


    initWebApplicationContext.png
    configureAndRefreshWebApplicationContext

    FrameworkServlet#configureAndRefreshWebApplicationContext配置和刷新Refresh web环境


    configureAndRefreshWebApplicationContext.png
    refresh

    AbstractApplicationContext#refresh 这个方法刷新spring web容器
    finishBeanFactoryInitialization()方法实例化所有不是lazy的单例对象


    refresh.png
    实例化

    具体的实例化过程经历完整的bean的生命周期,后面再单独介绍。

    handlerMap集合添加

    对beanName或alias是以/开头
    由于BeanNameUrlHandlerMapping实现了ApplicationContextAware方法,会执行initApplicationContext方法
    对于beanName是beanNameHandlerMapping

    initializeBean

    AbstractAutowireCapableBeanFactory#initializeBean(String,Object, RootBeanDefinition)


    applyBeanPostProcessorsBeforeInitialization.png
    applyBeanPostProcessorsBeforeInitialization

    AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization


    applyBeanPostProcessorsBeforeInitialization2.png
    postProcessBeforeInitialization

    ApplicationContextAwareProcessor#postProcessBeforeInitialization


    postProcessBeforeInitialization.png
    invokeAwareInterfaces

    ApplicationContextAwareProcessor#invokeAwareInterfaces


    invokeAwareInterfaces.png
    setApplicationContext

    ApplicationObjectSupport#setApplicationContext


    setApplicationContext.png
    initApplicationContext

    WebApplicationObjectSupport#initApplicationContext


    initApplicationContext.png
    initApplicationContext

    ApplicationObjectSupport#initApplicationContext(ApplicationContext)


    initApplicationContext2.png
    initApplicationContext

    AbstractDetectingUrlHandlerMapping#initApplicationContext


    initApplicationContext3.png
    detectHandlers

    AbstractDetectingUrlHandlerMapping#detectHandlers
    首先通过determineUrlsForHandler方法对beanName判断以/开头(别名或beanName)


    determineUrlsForHandler.png
    detectHandlers.png
    registerHandler

    AbstractUrlHandlerMapping#registerHandler(String[], String) 对符合beanName要求的bean进行注册


    registerHandler.png
    registerHandler

    AbstractUrlHandlerMapping#registerHandler(String, Object)


    registerHandler2.png

    在这里将会对所有beanName以/开头的添加。对实现Controller或HttpRequestHandler的注册

    mappingRegistry集合添加

    mappingRegistry内部集合其中一个是urlLookup集合
    在创建bean过程中,此时对beanName是requestMappingHandlerMapping的处理
    由于RequestMappingHandlerMapping实现了InitializingBean方法,所以将会在invokeInitMethods方法处理,在这里便会执行requestMappingHandlerMapping类的afterPropertiesSet方法

    initializeBean

    AbstractAutowireCapableBeanFactory#initializeBean
    initializeBean方法是初始化bean,依次会调用后置处理器的初始化之前方法(applyBeanPostProcessorsBeforeInitialization)、执行初始化方法、后置处理器的初始化之后方法(applyBeanPostProcessorsAfterInitialization)


    initializeBean.png
    invokeInitMethods

    AbstractAutowireCapableBeanFactory#invokeInitMethods执行实现了InitializingBean的afterPropertiesSet方法


    invokeInitMethods.png
    afterPropertiesSet

    RequestMappingHandlerMapping#afterPropertiesSet 此时RequestMappingHandlerMapping已经放到bean工厂里面


    afterPropertiesSet.png
    afterPropertiesSet

    AbstractHandlerMethodMapping#afterPropertiesSet RequestMappingHandlerMapping的父类执行


    afterPropertiesSetsuper.png
    initHandlerMethods

    AbstractHandlerMethodMapping#initHandlerMethods 扫描应用环境的bean,查找并注册Handler的Method
    首先判断是否需要从父容器查找,默认是detectHandlerMethodsInAncestorContexts=false。父子容器的含义:如果注册到父容器Handler的Method,在默认false的情况下将不会在父容器查找,这时只在子容器查找将会查找不到。如果设置true,将会从父容器查找,可以查到。


    父子容器获取.png

    遍历所有的beanName,查找符合isHandler的。带Controller或RequestMapping注解的


    isHandler.png
    查找Handler的Method(即是Controller的方法)
    initHandlerMethods.png
    detectHandlerMethods

    AbstractHandlerMethodMapping#detectHandlerMethods


    detectHandlerMethods.png

    对方法遍历用lambda表达式进行注册HandlerMethod


    lambda$detectHandlerMethods.png
    registerHandlerMethod

    AbstractHandlerMethodMapping#registerHandlerMethod 注册到mappingRegistry


    registerHandlerMethod.png
    register

    MappingRegistry#register 添加到urlLookup集合


    register.png

    到这里完成了对添加了Controller、RequestMapping注解的处理,添加到集合urlLookup。

    argumentResolvers初始化

    RequestMappingHandlerAdapter 实现了InitializingBean。所以,在实例化RequestMappingHandlerAdapter 过程中,会调用到afterPropertiesSet方法。
    RequestMappingHandlerAdapter#afterPropertiesSet


    afterPropertiesSet.png
    private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
            List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
    
            // Annotation-based argument resolution
            resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
            resolvers.add(new RequestParamMapMethodArgumentResolver());
            resolvers.add(new PathVariableMethodArgumentResolver());
            resolvers.add(new PathVariableMapMethodArgumentResolver());
            resolvers.add(new MatrixVariableMethodArgumentResolver());
            resolvers.add(new MatrixVariableMapMethodArgumentResolver());
            resolvers.add(new ServletModelAttributeMethodProcessor(false));
            resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
            resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
            resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
            resolvers.add(new RequestHeaderMapMethodArgumentResolver());
            resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
            resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
            resolvers.add(new SessionAttributeMethodArgumentResolver());
            resolvers.add(new RequestAttributeMethodArgumentResolver());
    
            // Type-based argument resolution
            resolvers.add(new ServletRequestMethodArgumentResolver());
            resolvers.add(new ServletResponseMethodArgumentResolver());
            resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
            resolvers.add(new RedirectAttributesMethodArgumentResolver());
            resolvers.add(new ModelMethodProcessor());
            resolvers.add(new MapMethodProcessor());
            resolvers.add(new ErrorsMethodArgumentResolver());
            resolvers.add(new SessionStatusMethodArgumentResolver());
            resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
    
            // Custom arguments
            if (getCustomArgumentResolvers() != null) {
                resolvers.addAll(getCustomArgumentResolvers());
            }
    
            // Catch-all
            resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
            resolvers.add(new ServletModelAttributeMethodProcessor(true));
    
            return resolvers;
        }
    
    argumentResolversSet.png

    initBinderArgumentResolvers集合

    实现在RequestMappingHandlerAdapter#afterPropertiesSet方法

    private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
            List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
    
            // Annotation-based argument resolution
            resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
            resolvers.add(new RequestParamMapMethodArgumentResolver());
            resolvers.add(new PathVariableMethodArgumentResolver());
            resolvers.add(new PathVariableMapMethodArgumentResolver());
            resolvers.add(new MatrixVariableMethodArgumentResolver());
            resolvers.add(new MatrixVariableMapMethodArgumentResolver());
            resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
            resolvers.add(new SessionAttributeMethodArgumentResolver());
            resolvers.add(new RequestAttributeMethodArgumentResolver());
    
            // Type-based argument resolution
            resolvers.add(new ServletRequestMethodArgumentResolver());
            resolvers.add(new ServletResponseMethodArgumentResolver());
    
            // Custom arguments
            if (getCustomArgumentResolvers() != null) {
                resolvers.addAll(getCustomArgumentResolvers());
            }
    
            // Catch-all
            resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    
            return resolvers;
        }
    

    returnValueHandlers集合

    实现在RequestMappingHandlerAdapter#afterPropertiesSet方法

    private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
            List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
    
            // Single-purpose return value types
            handlers.add(new ModelAndViewMethodReturnValueHandler());
            handlers.add(new ModelMethodProcessor());
            handlers.add(new ViewMethodReturnValueHandler());
            handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
                    this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
            handlers.add(new StreamingResponseBodyReturnValueHandler());
            handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
                    this.contentNegotiationManager, this.requestResponseBodyAdvice));
            handlers.add(new HttpHeadersReturnValueHandler());
            handlers.add(new CallableMethodReturnValueHandler());
            handlers.add(new DeferredResultMethodReturnValueHandler());
            handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
    
            // Annotation-based return value types
            handlers.add(new ModelAttributeMethodProcessor(false));
            handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
                    this.contentNegotiationManager, this.requestResponseBodyAdvice));
    
            // Multi-purpose return value types
            handlers.add(new ViewNameMethodReturnValueHandler());
            handlers.add(new MapMethodProcessor());
    
            // Custom return value types
            if (getCustomReturnValueHandlers() != null) {
                handlers.addAll(getCustomReturnValueHandlers());
            }
    
            // Catch-all
            if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
                handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
            }
            else {
                handlers.add(new ModelAttributeMethodProcessor(true));
            }
    
            return handlers;
        }
    

    initStrategies初始化initXXX集合

    通过观察者设计模式实现
    包括handlerMappings、handlerAdapters

    refresh

    finishBeanFactoryInitialization完成实例化之后,调用finishRefresh方法。


    finishrefresh.png
    finishRefresh

    AbstractApplicationContext#finishRefresh 发布ContextRefreshedEvent上下文刷新事件


    finishrefresh.png
    publishEvent

    AbstractApplicationContext#publishEvent(ApplicationEvent) 发布被给的事件给所有的监听者(listeners)
    监听者初始化是在MessageSource之后,为了能够在监听器实现访问它,因此MessageSource实现不能发布事件


    publishEvent.png
    publishEvent

    AbstractApplicationContext#publishEvent(Object, ResolvableType)发布被给的事件给所有的监听者(listeners)如果可能的话,使用多播


    publishEvent2.png
    multicastEvent

    SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType) 应用事件多播者广播事件。对所有的符合当前事件类型的监听器进行查找并遍历执行


    SAEmulticastEvent.png
    invokeListener

    SimpleApplicationEventMulticaster#invokeListener 用给定的事件执行给定的监听器


    invokeListener.png
    doInvokeListener

    SimpleApplicationEventMulticaster#doInvokeListener 监听器执行事件


    doInvokeListener.png
    onApplicationEvent

    SourceFilteringListener#onApplicationEvent 具体监听器执行


    onApplicationEvent.png
    onApplicationEventInternal

    SourceFilteringListener#onApplicationEventInternal 根据过滤事件源之后的实际执行事件。如果有的话,默认实现通过调用指定的委托类。
    在这里首先要搞清楚SourceFilteringListener#delegate代理类是什么时候被赋值的。在执行refresh()方法之前的addApplicationListener方法。


    addApplicationListener.png

    创建SourceFilteringListener对象


    SourceFilteringListener.png
    SourceFilteringListener#onApplicationEventInternal
    onApplicationEventInternal.png
    onApplicationEvent

    GenericApplicationListenerAdapter#onApplicationEvent 委托类执行


    onApplicationEvent2.png
    onApplicationEvent

    ContextRefreshListener#onApplicationEvent 在FrameworkServlet的实例中对于来自servlet的WebApplicationContext(web应用上下文)的ApplicationListener,只委托给onApplicationEvent方法。FrameworkServlet.this是DispatcherServlet


    onApplicationEvent3.png
    onApplicationEvent

    FrameworkServlet#onApplicationEvent 从这个servlet的WebApplicationContext中接收刷新事件的回调。触发刷新这个servlet的上下文相关状态


    DSonApplicationEvent.png
    onRefresh

    DispatcherServlet#onRefresh 刷新应用上下文,这个实现调用initStrategies方法


    onRefresh.png
    initStrategies

    DispatcherServlet#initStrategies 初始化这个servlet使用的策略对象。可以在子类中被覆盖,以便进一步初始化策略。

    initStrategies.png
    1、initMultipartResolver
    在容器中查找beanName是multipartResolver,类型是MultipartResolver的类。结果返回空
    initMultipartResolver.png
    2、initLocaleResolver
    在容器中查找beanName是localeResolver,类型是LocaleResolver的类。如果返回空,使用默认的AcceptHeaderLocaleResolver
    initLocaleResolver.png
    3、initThemeResolver
    在容器中查找beanName是themeResolver,类型是ThemeResolver的类。如果返回空,使用默认的FixedThemeResolver
    initThemeResolver.png
    4、initHandlerMappings
    DispatcherServlet#initHandlerMappings
    从所有容器(父子容器)查找。类型是HandlerMapping的类,默认BeanNameUrlHandlerMapping
    initHandlerMappings.png
    5、initHandlerAdapters
    从所有容器(父子容器)查找。类型是HandlerAdapter的类,默认SimpleControllerHandlerAdapter
    initHandlerAdapters.png
    6、initHandlerExceptionResolvers
    类型是HandlerExceptionResolver
    initHandlerExceptionResolvers.png
    7、initRequestToViewNameTranslator
    在容器中查找beanName是viewNameTranslator 类型是RequestToViewNameTranslator
    initRequestToViewNameTranslator.png
    8、initViewResolvers
    DispatcherServlet#initViewResolvers
    initViewResolvers.png
    9、initFlashMapManager
    返回SessionFlashMapManager
    initFlashMapManager.png

    @EnableWebMvc注解

    在初始化initStrategies过程中,web容器中能够找到那么多不知道什么时候添加的HandlerMapping、HandlerAdapter等等
    在实例代码中AppConfig类中使用了EnableWebMvc 注解,源码如下。
    开启EnableWebMvc将会导入(import)DelegatingWebMvcConfiguration类,而DelegatingWebMvcConfiguration 继承了WebMvcConfigurationSupport 类。在WebMvcConfigurationSupport 中有18个@Bean方法

    package org.springframework.web.servlet.config.annotation;
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(DelegatingWebMvcConfiguration.class)
    public @interface EnableWebMvc {
    }
    
    @Configuration
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    }
    
    
    
    package org.springframework.web.servlet.config.annotation;
    public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
    
        
        @Bean
        public RequestMappingHandlerMapping requestMappingHandlerMapping() {
            RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
            mapping.setOrder(0);
            mapping.setInterceptors(getInterceptors());
            mapping.setContentNegotiationManager(mvcContentNegotiationManager());
            mapping.setCorsConfigurations(getCorsConfigurations());
    
            PathMatchConfigurer configurer = getPathMatchConfigurer();
    
            Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();
            if (useSuffixPatternMatch != null) {
                mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
            }
            Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();
            if (useRegisteredSuffixPatternMatch != null) {
                mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
            }
            Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
            if (useTrailingSlashMatch != null) {
                mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
            }
    
            UrlPathHelper pathHelper = configurer.getUrlPathHelper();
            if (pathHelper != null) {
                mapping.setUrlPathHelper(pathHelper);
            }
            PathMatcher pathMatcher = configurer.getPathMatcher();
            if (pathMatcher != null) {
                mapping.setPathMatcher(pathMatcher);
            }
    
            return mapping;
        }
    
        
        @Bean
        public PathMatcher mvcPathMatcher() {
            PathMatcher pathMatcher = getPathMatchConfigurer().getPathMatcher();
            return (pathMatcher != null ? pathMatcher : new AntPathMatcher());
        }
    
        @Bean
        public UrlPathHelper mvcUrlPathHelper() {
            UrlPathHelper pathHelper = getPathMatchConfigurer().getUrlPathHelper();
            return (pathHelper != null ? pathHelper : new UrlPathHelper());
        }
    
    
        @Bean
        public ContentNegotiationManager mvcContentNegotiationManager() {
            if (this.contentNegotiationManager == null) {
                ContentNegotiationConfigurer configurer = new ContentNegotiationConfigurer(this.servletContext);
                configurer.mediaTypes(getDefaultMediaTypes());
                configureContentNegotiation(configurer);
                this.contentNegotiationManager = configurer.buildContentNegotiationManager();
            }
            return this.contentNegotiationManager;
        }
    
        
        @Bean
        public HandlerMapping viewControllerHandlerMapping() {
            ViewControllerRegistry registry = new ViewControllerRegistry(this.applicationContext);
            addViewControllers(registry);
    
            AbstractHandlerMapping handlerMapping = registry.buildHandlerMapping();
            handlerMapping = (handlerMapping != null ? handlerMapping : new EmptyHandlerMapping());
            handlerMapping.setPathMatcher(mvcPathMatcher());
            handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
            handlerMapping.setInterceptors(getInterceptors());
            handlerMapping.setCorsConfigurations(getCorsConfigurations());
            return handlerMapping;
        }
        
        @Bean
        public BeanNameUrlHandlerMapping beanNameHandlerMapping() {
            BeanNameUrlHandlerMapping mapping = new BeanNameUrlHandlerMapping();
            mapping.setOrder(2);
            mapping.setInterceptors(getInterceptors());
            mapping.setCorsConfigurations(getCorsConfigurations());
            return mapping;
        }
    
        
        @Bean
        public HandlerMapping resourceHandlerMapping() {
            Assert.state(this.applicationContext != null, "No ApplicationContext set");
            Assert.state(this.servletContext != null, "No ServletContext set");
    
            ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
                    this.servletContext, mvcContentNegotiationManager(), mvcUrlPathHelper());
            addResourceHandlers(registry);
    
            AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
            if (handlerMapping != null) {
                handlerMapping.setPathMatcher(mvcPathMatcher());
                handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
                handlerMapping.setInterceptors(getInterceptors());
                handlerMapping.setCorsConfigurations(getCorsConfigurations());
            }
            else {
                handlerMapping = new EmptyHandlerMapping();
            }
            return handlerMapping;
        }
    
    
        @Bean
        public ResourceUrlProvider mvcResourceUrlProvider() {
            ResourceUrlProvider urlProvider = new ResourceUrlProvider();
            UrlPathHelper pathHelper = getPathMatchConfigurer().getUrlPathHelper();
            if (pathHelper != null) {
                urlProvider.setUrlPathHelper(pathHelper);
            }
            PathMatcher pathMatcher = getPathMatchConfigurer().getPathMatcher();
            if (pathMatcher != null) {
                urlProvider.setPathMatcher(pathMatcher);
            }
            return urlProvider;
        }
    
    
        @Bean
        public HandlerMapping defaultServletHandlerMapping() {
            Assert.state(this.servletContext != null, "No ServletContext set");
            DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(this.servletContext);
            configureDefaultServletHandling(configurer);
    
            HandlerMapping handlerMapping = configurer.buildHandlerMapping();
            return (handlerMapping != null ? handlerMapping : new EmptyHandlerMapping());
        }
    
        
        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
            adapter.setContentNegotiationManager(mvcContentNegotiationManager());
            adapter.setMessageConverters(getMessageConverters());
            adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());
            adapter.setCustomArgumentResolvers(getArgumentResolvers());
            adapter.setCustomReturnValueHandlers(getReturnValueHandlers());
    
            if (jackson2Present) {
                adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
                adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
            }
    
            AsyncSupportConfigurer configurer = new AsyncSupportConfigurer();
            configureAsyncSupport(configurer);
            if (configurer.getTaskExecutor() != null) {
                adapter.setTaskExecutor(configurer.getTaskExecutor());
            }
            if (configurer.getTimeout() != null) {
                adapter.setAsyncRequestTimeout(configurer.getTimeout());
            }
            adapter.setCallableInterceptors(configurer.getCallableInterceptors());
            adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
    
            return adapter;
        }
    
        
        @Bean
        public FormattingConversionService mvcConversionService() {
            FormattingConversionService conversionService = new DefaultFormattingConversionService();
            addFormatters(conversionService);
            return conversionService;
        }
    
        
        @Bean
        public Validator mvcValidator() {
            Validator validator = getValidator();
            if (validator == null) {
                if (ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) {
                    Class<?> clazz;
                    try {
                        String className = "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean";
                        clazz = ClassUtils.forName(className, WebMvcConfigurationSupport.class.getClassLoader());
                    }
                    catch (ClassNotFoundException | LinkageError ex) {
                        throw new BeanInitializationException("Failed to resolve default validator class", ex);
                    }
                    validator = (Validator) BeanUtils.instantiateClass(clazz);
                }
                else {
                    validator = new NoOpValidator();
                }
            }
            return validator;
        }
    
        
        @Bean
        public CompositeUriComponentsContributor mvcUriComponentsContributor() {
            return new CompositeUriComponentsContributor(
                    requestMappingHandlerAdapter().getArgumentResolvers(), mvcConversionService());
        }
    
    
        @Bean
        public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
            return new HttpRequestHandlerAdapter();
        }
    
        
        @Bean
        public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
            return new SimpleControllerHandlerAdapter();
        }
    
    
        @Bean
        public HandlerExceptionResolver handlerExceptionResolver() {
            List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
            configureHandlerExceptionResolvers(exceptionResolvers);
            if (exceptionResolvers.isEmpty()) {
                addDefaultHandlerExceptionResolvers(exceptionResolvers);
            }
            extendHandlerExceptionResolvers(exceptionResolvers);
            HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
            composite.setOrder(0);
            composite.setExceptionResolvers(exceptionResolvers);
            return composite;
        }
    
        
        @Bean
        public ViewResolver mvcViewResolver() {
            ViewResolverRegistry registry = new ViewResolverRegistry(
                    mvcContentNegotiationManager(), this.applicationContext);
            configureViewResolvers(registry);
    
            if (registry.getViewResolvers().isEmpty() && this.applicationContext != null) {
                String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.applicationContext, ViewResolver.class, true, false);
                if (names.length == 1) {
                    registry.getViewResolvers().add(new InternalResourceViewResolver());
                }
            }
    
            ViewResolverComposite composite = new ViewResolverComposite();
            composite.setOrder(registry.getOrder());
            composite.setViewResolvers(registry.getViewResolvers());
            if (this.applicationContext != null) {
                composite.setApplicationContext(this.applicationContext);
            }
            if (this.servletContext != null) {
                composite.setServletContext(this.servletContext);
            }
            return composite;
        }
    }
    
    

    所以,在导入这个类之后,这些@Bean将会使用配置类的@Bean方法进行处理


    beanMethods.png

    总结:

    本章主要分析,request请求之前的源码级别的初始化过程。
    从tomcat初始化init开始加载web级别容器上下文的初始化
    1、初始化web容器上下文环境
    2、EnableWebMvc注解使用Bean方法,放到web容器中
    3、initApplicationContext方法,以/开头的添加到handlerMap集合
    4、afterPropertiesSet方法,把Controller、RequestMapping注解方法放到mappingRegistry的集合urlLookup之中
    5、argumentResolvers、initBinderArgumentResolvers、returnValueHandlers集合初始化
    6、initStrategies策略,对springMVC使用的集合进行赋值。finishRefresh()完成刷新,发布事件。使用观察者设计模式(监听器)

    相关文章

      网友评论

        本文标题:springMVC源码分析初始化过程

        本文链接:https://www.haomeiwen.com/subject/biboictx.html