美文网首页
Spring MVC(2)2018-08-07

Spring MVC(2)2018-08-07

作者: Seetheworl_6675 | 来源:发表于2018-08-07 21:48 被阅读0次

     上一节Spring MVC(1)我们简单的过了DispatcherServelt的初始化的过程,今天我们继续看看Spring MVC组件的初始化过程。

    pring MVC组件的初始化过程

    Spring MVC(1)最后代码:

    protected void initStrategies(ApplicationContext context) {
            initMultipartResolver(context);//文件上传解析
            initLocaleResolver(context);//本地解析
            initThemeResolver(context);//主题解析
            initHandlerMappings(context);//url请求映射
            initHandlerAdapters(context);//初始化真正调用controloler方法的类
            initHandlerExceptionResolvers(context);//异常解析
            initRequestToViewNameTranslator(context);//视图名称翻译器
            initViewResolvers(context);//视图解析
            initFlashMapManager(context);//重定向数据管理器
        }
    
    initMultipartResolver:文件上传解析器

     我们首先来看一下initMultipartResolver这个方法的内容:

     private void initMultipartResolver(ApplicationContext context) {
            try {
                //从上下文中获取bean name为multipartResolver
                this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
                }
            } catch (NoSuchBeanDefinitionException var3) {
                this.multipartResolver = null;
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided");
                }
            }
    
        }
    

     这个方法的内容就是从上下文中获取bean name为multipartResolver,类型为MultipartResolver.class的bean,如果没有获取到到Bean的话则multipartResolver 为null。

    initLocaleResolver:本地解析器

    我们继续看一下initLocaleResolver这个方法的内容,代码如下:

    private void initLocaleResolver(ApplicationContext context) {
            try {
                 //从上下文中获取bean name为localeResolver
                this.localeResolver = (LocaleResolver)context.getBean("localeResolver", LocaleResolver.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Using LocaleResolver [" + this.localeResolver + "]");
                }
            } catch (NoSuchBeanDefinitionException var3) {
                this.localeResolver = (LocaleResolver)this.getDefaultStrategy(context, LocaleResolver.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Unable to locate LocaleResolver with name 'localeResolver': using default [" + this.localeResolver + "]");
                }
            }
    
        }
    
    

     从上面的代码中我们可以看到组装本地解析器的时候会先从上下文中获取name为localeResolver,类型为LocaleResolver.class的bean,如果没有获取到,则调用getDefaultStrategy这个方法获取默认的LocaleResolver。我们进入到getDefaultStrategy这个方法中看一下这个方法做了哪些事情:

    protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
            //获取默认的组件
            List<T> strategies = this.getDefaultStrategies(context, strategyInterface);
            if (strategies.size() != 1) {
                throw new BeanInitializationException("DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
            } else {
                return strategies.get(0);
            }
        }
    

     继续调用getDefaultStrategies这个方法来获取默认的LocaleResolver,并且LocaleResolver的数量只能有一个。我们来看一下getDefaultStrategies这个方法:

    protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
            //获取全限定类名(包名+类名)
            String key = strategyInterface.getName();
            //根据获取到的类名取相应的值
            String value = defaultStrategies.getProperty(key);
            if (value == null) {
                return new LinkedList();
            } else {
                //将获取到的值根据","进行分割
                String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
                //创建指定长度的集合
                List<T> strategies = new ArrayList(classNames.length);
                String[] var7 = classNames;
                int var8 = classNames.length;
    
                for(int var9 = 0; var9 < var8; ++var9) {
                    String className = var7[var9];
    
                    try {
                        //反射获取相应的类对象
                        Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
                        //实例化相应的类,并放到上下文中
                        Object strategy = this.createDefaultStrategy(context, clazz);
                        //添加到集合中
                        strategies.add(strategy);
                    } catch (ClassNotFoundException var13) {
                        throw new BeanInitializationException("Could not find DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var13);
                    } catch (LinkageError var14) {
                        throw new BeanInitializationException("Unresolvable class definition for DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var14);
                    }
                }
    
                return strategies;
            }
        }
    

    defaultStrategies是其中比较重要的一个属性,我们看一下它是什么,在DispatcherServlet中的定义和初始化的:

    private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
    
    //是一个Properties
    private static final Properties defaultStrategies;
    
        static {
            // Load default strategy implementations from properties file.
            // This is currently strictly internal and not meant to be customized
            // by application developers.
            try {  
                            //
                ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
                defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
            }
            catch (IOException ex) {
                throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
            }
        }
    

     从上面的代码中我们发现为defaultStrategies赋值的过程是在静态代码块中进行的,我们知道静态代码块会在类初始化的时候执行。

    SpringMVC默认组件

    DispatcherServlet.properties在这个文件中指定了一下默认的组件,如下所示:

    ## 本地化解析器
    org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
    
    ## 主题解析器
    org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
    
    ## 处理器映射(2个)
    org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
    
    
    ## 处理器适配器(3个)
    org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
    
    ## 异常处理器(3个)
    org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
    
    ## 视图名称翻译器
    org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
    
    ## 视图解析器
    org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
    
    ## 重定向数据管理器
    org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
    
    initThemeResolver:主题解析
    private void initThemeResolver(ApplicationContext context) {
            try {
                this.themeResolver = (ThemeResolver)context.getBean("themeResolver", ThemeResolver.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Using ThemeResolver [" + this.themeResolver + "]");
                }
            } catch (NoSuchBeanDefinitionException var3) {
                this.themeResolver = (ThemeResolver)this.getDefaultStrategy(context, ThemeResolver.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Unable to locate ThemeResolver with name 'themeResolver': using default [" + this.themeResolver + "]");
                }
            }
    
        }
    

    从上面的代码中我们可以看出来它和本地化解析器(initLocaleResolver)的初始化过程是一样的,就不在具体分析了。

    initHandlerMappings:url请求映射
    private void initHandlerMappings(ApplicationContext context) {
            this.handlerMappings = null;
            //检测所有处理程序映射
            if (this.detectAllHandlerMappings) {
                //从上下文中查找所有的HandlerMapping实现类
                Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
                if (!matchingBeans.isEmpty()) {
                    this.handlerMappings = new ArrayList(matchingBeans.values());
                    AnnotationAwareOrderComparator.sort(this.handlerMappings);
                }
            } else {
                try {
                    //这里只取固定的bean
                    HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
                    this.handlerMappings = Collections.singletonList(hm);
                } catch (NoSuchBeanDefinitionException var3) {
                    ;
                }
            }
            //如果上面都没有取到HandlerMapping,则取默认的HandlerMapping
            if (this.handlerMappings == null) {
                this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("No HandlerMappings found in servlet '" + this.getServletName() + "': using default");
                }
            }
    
        }
    

     从上面的代码中我们可以看到如果detectAllHandlerMappings为true的话,则从上下文中查找所有类型为HandlerMapping的的bean,如果detectAllHandlerMappings为false的话,则从上下文中查找bean的名字为handlerMapping,类型为HandlerMapping的bean。如果这两步都取不到bean的话,则从DispatcherServlet.properties中查找默认的HandlerMapping类型的bean。

    initHandlerAdapters:适配器
    private void initHandlerAdapters(ApplicationContext context) {
            this.handlerAdapters = null;
            if (this.detectAllHandlerAdapters) {
                Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
                if (!matchingBeans.isEmpty()) {
                    this.handlerAdapters = new ArrayList(matchingBeans.values());
                    AnnotationAwareOrderComparator.sort(this.handlerAdapters);
                }
            } else {
                try {
                    HandlerAdapter ha = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class);
                    this.handlerAdapters = Collections.singletonList(ha);
                } catch (NoSuchBeanDefinitionException var3) {
                    ;
                }
            }
    
            if (this.handlerAdapters == null) {
                this.handlerAdapters = this.getDefaultStrategies(context, HandlerAdapter.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("No HandlerAdapters found in servlet '" + this.getServletName() + "': using default");
                }
            }
    
        }
    
    

     处理器适配器的初始化过程和处理器映射器的初始化过程基本上是一致的

    initHandlerExceptionResolvers:异常解析器
    private void initHandlerExceptionResolvers(ApplicationContext context) {
            this.handlerExceptionResolvers = null;
            if (this.detectAllHandlerExceptionResolvers) {
                Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
                if (!matchingBeans.isEmpty()) {
                    this.handlerExceptionResolvers = new ArrayList(matchingBeans.values());
                    AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
                }
            } else {
                try {
                    HandlerExceptionResolver her = (HandlerExceptionResolver)context.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
                    this.handlerExceptionResolvers = Collections.singletonList(her);
                } catch (NoSuchBeanDefinitionException var3) {
                    ;
                }
            }
    
            if (this.handlerExceptionResolvers == null) {
                this.handlerExceptionResolvers = this.getDefaultStrategies(context, HandlerExceptionResolver.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("No HandlerExceptionResolvers found in servlet '" + this.getServletName() + "': using default");
                }
            }
    
        }
    

    异常处理器的初始化过程同上。
     异常处理器的初始化过程和处理器映射器的初始化过程基本上是一致的

    initRequestToViewNameTranslator:视图名称翻译器
    private void initRequestToViewNameTranslator(ApplicationContext context) {
            try {
                this.viewNameTranslator = (RequestToViewNameTranslator)context.getBean("viewNameTranslator", RequestToViewNameTranslator.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]");
                }
            } catch (NoSuchBeanDefinitionException var3) {
                this.viewNameTranslator = (RequestToViewNameTranslator)this.getDefaultStrategy(context, RequestToViewNameTranslator.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Unable to locate RequestToViewNameTranslator with name 'viewNameTranslator': using default [" + this.viewNameTranslator + "]");
                }
            }
    
        }
    

     同上;

    initViewResolvers:视图解析器
    private void initViewResolvers(ApplicationContext context) {
            this.viewResolvers = null;
            if (this.detectAllViewResolvers) {
                Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
                if (!matchingBeans.isEmpty()) {
                    this.viewResolvers = new ArrayList(matchingBeans.values());
                    AnnotationAwareOrderComparator.sort(this.viewResolvers);
                }
            } else {
                try {
                    ViewResolver vr = (ViewResolver)context.getBean("viewResolver", ViewResolver.class);
                    this.viewResolvers = Collections.singletonList(vr);
                } catch (NoSuchBeanDefinitionException var3) {
                    ;
                }
            }
    
            if (this.viewResolvers == null) {
                this.viewResolvers = this.getDefaultStrategies(context, ViewResolver.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("No ViewResolvers found in servlet '" + this.getServletName() + "': using default");
                }
            }
    
        }
    

     同上;

    initFlashMapManager:重定向数据管理器
    private void initFlashMapManager(ApplicationContext context) {
            try {
                this.flashMapManager = (FlashMapManager)context.getBean("flashMapManager", FlashMapManager.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Using FlashMapManager [" + this.flashMapManager + "]");
                }
            } catch (NoSuchBeanDefinitionException var3) {
                this.flashMapManager = (FlashMapManager)this.getDefaultStrategy(context, FlashMapManager.class);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Unable to locate FlashMapManager with name 'flashMapManager': using default [" + this.flashMapManager + "]");
                }
            }
    
        }
    

     同上;

    相关文章

      网友评论

          本文标题:Spring MVC(2)2018-08-07

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