Spring MVC(2)2018-08-07

?上一節(jié)Spring MVC(1)我們簡單的過了DispatcherServelt的初始化的過程,今天我們繼續(xù)看看Spring MVC組件的初始化過程。

pring MVC組件的初始化過程

Spring MVC(1)最后代碼:

protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);//文件上傳解析
        initLocaleResolver(context);//本地解析
        initThemeResolver(context);//主題解析
        initHandlerMappings(context);//url請(qǐng)求映射
        initHandlerAdapters(context);//初始化真正調(diào)用controloler方法的類
        initHandlerExceptionResolvers(context);//異常解析
        initRequestToViewNameTranslator(context);//視圖名稱翻譯器
        initViewResolvers(context);//視圖解析
        initFlashMapManager(context);//重定向數(shù)據(jù)管理器
    }
initMultipartResolver:文件上傳解析器

?我們首先來看一下initMultipartResolver這個(gè)方法的內(nèi)容:

 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");
            }
        }

    }

?這個(gè)方法的內(nèi)容就是從上下文中獲取bean name為multipartResolver,類型為MultipartResolver.class的bean,如果沒有獲取到到Bean的話則multipartResolver 為null。

initLocaleResolver:本地解析器

我們繼續(xù)看一下initLocaleResolver這個(gè)方法的內(nèi)容,代碼如下:

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 + "]");
            }
        }

    }

?從上面的代碼中我們可以看到組裝本地解析器的時(shí)候會(huì)先從上下文中獲取name為localeResolver,類型為LocaleResolver.class的bean,如果沒有獲取到,則調(diào)用getDefaultStrategy這個(gè)方法獲取默認(rèn)的LocaleResolver。我們進(jìn)入到getDefaultStrategy這個(gè)方法中看一下這個(gè)方法做了哪些事情:

protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
        //獲取默認(rèn)的組件
        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);
        }
    }

?繼續(xù)調(diào)用getDefaultStrategies這個(gè)方法來獲取默認(rèn)的LocaleResolver,并且LocaleResolver的數(shù)量只能有一個(gè)。我們來看一下getDefaultStrategies這個(gè)方法:

protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
        //獲取全限定類名(包名+類名)
        String key = strategyInterface.getName();
        //根據(jù)獲取到的類名取相應(yīng)的值
        String value = defaultStrategies.getProperty(key);
        if (value == null) {
            return new LinkedList();
        } else {
            //將獲取到的值根據(jù)","進(jìn)行分割
            String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
            //創(chuàng)建指定長度的集合
            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 {
                    //反射獲取相應(yīng)的類對(duì)象
                    Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
                    //實(shí)例化相應(yīng)的類,并放到上下文中
                    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是其中比較重要的一個(gè)屬性,我們看一下它是什么,在DispatcherServlet中的定義和初始化的:

private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";

//是一個(gè)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());
        }
    }

?從上面的代碼中我們發(fā)現(xiàn)為defaultStrategies賦值的過程是在靜態(tài)代碼塊中進(jìn)行的,我們知道靜態(tài)代碼塊會(huì)在類初始化的時(shí)候執(zhí)行。

SpringMVC默認(rèn)組件

DispatcherServlet.properties在這個(gè)文件中指定了一下默認(rèn)的組件,如下所示:

## 本地化解析器
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

## 主題解析器
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

## 處理器映射(2個(gè))
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping


## 處理器適配器(3個(gè))
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個(gè))
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

## 重定向數(shù)據(jù)管理器
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請(qǐng)求映射
private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;
        //檢測(cè)所有處理程序映射
        if (this.detectAllHandlerMappings) {
            //從上下文中查找所有的HandlerMapping實(shí)現(xiàn)類
            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,則取默認(rèn)的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中查找默認(rèn)的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:重定向數(shù)據(jù)管理器
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 + "]");
            }
        }

    }

?同上;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,931評(píng)論 1 92
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,844評(píng)論 2 22
  • 1.1 Spring IoC容器和bean簡介 本章介紹了Spring Framework實(shí)現(xiàn)的控制反轉(zhuǎn)(IoC)...
    起名真是難閱讀 2,665評(píng)論 0 8
  • 1.Spring整體架構(gòu) 1)核心容器(Core Container) Core模塊,主要包含了Spring框架基...
    Sponge1128閱讀 1,251評(píng)論 0 1
  • 引言 一直以來都在使用Spring mvc,能夠熟練使用它的各種組件。但是,它一直像個(gè)黑盒一樣,我并不知道它內(nèi)部是...
    yoqu閱讀 950評(píng)論 0 24

友情鏈接更多精彩內(nèi)容