最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解spring注解配置啟動(dòng)過程

 更新時(shí)間:2016年10月17日 11:15:54   作者:暮夜望日  
這篇文章主要為大家詳細(xì)介紹了詳解spring注解配置啟動(dòng)過程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

       最近看起spring源碼,突然想知道沒有web.xml的配置,spring是怎么通過一個(gè)繼承于AbstractAnnotationConfigDispatcherServletInitializer的類來啟動(dòng)自己的。鑒于能力有限以及第一次看源碼和發(fā)博客,不到之處請望諒~

  我用的IDE是IntelliJ IDEA,這個(gè)比myEclipse看源碼方便一點(diǎn),而且黑色背景挺喜歡。然后項(xiàng)目是在maven下的tomcat7插件運(yùn)行。spring版本是4.3.2.RELEASE。 

  如果寫過純注解配置的spring web,應(yīng)該知道需要繼承一個(gè)初始化類來裝載bean,然后從這個(gè)類開始就會(huì)加載我們自定義的功能和bean了,下面是我的一個(gè)WebInitializer

@Order(1)
public class WebMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {
 protected Class<?>[] getRootConfigClasses() {
  return new Class[]{RootConfig.class,WebSecurityConfig.class};
 }

 protected Class<?>[] getServletConfigClasses() {
  return new Class[]{WebConfig.class};
 }

 protected String[] getServletMappings() {
  return new String[]{"/"};
 }

 @Override
 protected Filter[] getServletFilters() {
  return new Filter[]{new HiddenHttpMethodFilter()};
 }

}

  首先看下AbstractAnnotationConfigDispatcherServletInitializer類的結(jié)構(gòu),這個(gè)也是IDEA的一個(gè)uml功能,在類那里右鍵Diagrams->show Diagrams就有啦

  然后我們直接點(diǎn)進(jìn)AbstractAnnotationConfigDispatcherServletInitializer,可以看到這個(gè)類很簡單,只有四個(gè)方法,然后我們關(guān)注下createRootApplicationContext()

@Override
 protected WebApplicationContext createRootApplicationContext() {
  Class<?>[] configClasses = getRootConfigClasses();
  if (!ObjectUtils.isEmpty(configClasses)) {
   AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
   rootAppContext.register(configClasses);
   return rootAppContext;
  }
  else {
   return null;
  }
 } 

  這個(gè)方法大概意思是獲取用戶(程序員)傳過來的RootClasses,然后注冊里面的bean,這些都不是我們關(guān)注的,不過這個(gè)方法應(yīng)該是要在啟動(dòng)后執(zhí)行的,所以我們可以從這個(gè)方法往上找

  IDEA下Ctrl+G可以找調(diào)用某個(gè)方法或類,然后設(shè)置尋找范圍為project and library

  我們找到,AbstractContextLoaderInitializer下registerContextLoaderListener(ServletContext servletContext)方法調(diào)用子類的createRootApplicationContext()獲取WebApplicationContext,繼續(xù)找registerContextLoaderListener(ServletContext servletContext)方法的調(diào)用者,結(jié)果發(fā)現(xiàn)就是該類下的onStartup(ServletContext servletContext),下面貼下AbstractContextLoaderInitializer類

public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {

 /** Logger available to subclasses */
 protected final Log logger = LogFactory.getLog(getClass());


 @Override
 public void onStartup(ServletContext servletContext) throws ServletException {
  registerContextLoaderListener(servletContext);
 }

 /**
  * Register a {@link ContextLoaderListener} against the given servlet context. The
  * {@code ContextLoaderListener} is initialized with the application context returned
  * from the {@link #createRootApplicationContext()} template method.
  * @param servletContext the servlet context to register the listener against
  */
 protected void registerContextLoaderListener(ServletContext servletContext) {
  WebApplicationContext rootAppContext = createRootApplicationContext();
  if (rootAppContext != null) {
   ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
   listener.setContextInitializers(getRootApplicationContextInitializers());
   servletContext.addListener(listener);
  }
  else {
   logger.debug("No ContextLoaderListener registered, as " +
     "createRootApplicationContext() did not return an application context");
  }
 }

 /**
  * Create the "<strong>root</strong>" application context to be provided to the
  * {@code ContextLoaderListener}.
  * <p>The returned context is delegated to
  * {@link ContextLoaderListener#ContextLoaderListener(WebApplicationContext)} and will
  * be established as the parent context for any {@code DispatcherServlet} application
  * contexts. As such, it typically contains middle-tier services, data sources, etc.
  * @return the root application context, or {@code null} if a root context is not
  * desired
  * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer
  */
 protected abstract WebApplicationContext createRootApplicationContext();

 /**
  * Specify application context initializers to be applied to the root application
  * context that the {@code ContextLoaderListener} is being created with.
  * @since 4.2
  * @see #createRootApplicationContext()
  * @see ContextLoaderListener#setContextInitializers
  */
 protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
  return null;
 }

}

  注意的是這里我們跳過了AbstractDispatcherServletInitializer抽象類(看uml圖),這個(gè)類主要配置DispatcherServlet,這里就是spring mvc等功能的實(shí)現(xiàn)了。 

  那誰來加載AbstractContextLoaderInitializer?WebApplicationInitializer已經(jīng)是接口,不會(huì)再有一個(gè)抽象類來調(diào)用了,于是我嘗試性地搜WebApplicationInitializer接口,因?yàn)閟pring這種大項(xiàng)目肯定是面向接口的,所以調(diào)用的地方一般是寫接口,然后我們找到了SpringServletContainerInitializer類,它實(shí)現(xiàn)了ServletContainerInitializer接口,這個(gè)類大概是說把所有WebApplicationInitializer都startUp一遍,可以說這個(gè)類很接近我們的目標(biāo)了。下面貼下SpringServletContainerInitializer

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
 @Override
 public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
   throws ServletException {

  List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

  if (webAppInitializerClasses != null) {
   for (Class<?> waiClass : webAppInitializerClasses) {
    // Be defensive: Some servlet containers provide us with invalid classes,
    // no matter what @HandlesTypes says...
    if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
      WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
     try {
      initializers.add((WebApplicationInitializer) waiClass.newInstance());
     }
     catch (Throwable ex) {
      throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
     }
    }
   }
  }

  if (initializers.isEmpty()) {
   servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
   return;
  }

  servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
  AnnotationAwareOrderComparator.sort(initializers);
  for (WebApplicationInitializer initializer : initializers) {
   initializer.onStartup(servletContext);
  }
 }

}
  

         在最后的foreach把所有的WebApplicationInitializer都啟動(dòng)一遍。那么問題來了,誰來啟動(dòng)SpringServletContainerInitializer,spring肯定不能自己就能啟動(dòng)的,在

         web環(huán)境下,就只有web容器了。我們可以在上面某一個(gè)地方打個(gè)斷點(diǎn),然后Debug一下(事實(shí)上,完全可以全程Debug = =,這樣準(zhǔn)確又快捷,不過這樣少了點(diǎn)尋找的意味,沿路風(fēng)景還是挺不錯(cuò)的) 

  可以看到包org.apache.catalina.core下的StandardContext類的startInternal方法,這個(gè)已經(jīng)是tomcat的范圍了,所以我們的目標(biāo)算是達(dá)到了。注意的是ServletContainerInitializer接口并不是spring包下的,而是javax.servlet

  我猜測,tomcat通過javax.servlet的ServletContainerInitializer接口來找容器下實(shí)現(xiàn)這個(gè)接口的類,然后調(diào)用它們的OnStartUp,然后spring的SpringServletContainerInitializer就可以把所有WebApplicationInitializer都啟動(dòng)一遍,其中就有我們自己寫的WebInitializer,另外spring security用注解配置也是實(shí)現(xiàn)WebApplicationInitializer啟動(dòng)的,所以這樣spring的擴(kuò)展性很強(qiáng)。這幾天再看下tomcat源碼,了解下tomcat的機(jī)制。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring是怎么擴(kuò)展解析xml接口的

    Spring是怎么擴(kuò)展解析xml接口的

    這篇文章主要介紹了Spring是怎么擴(kuò)展解析xml接口的,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • MyBatis之自查詢使用遞歸實(shí)現(xiàn) N級聯(lián)動(dòng)效果(兩種實(shí)現(xiàn)方式)

    MyBatis之自查詢使用遞歸實(shí)現(xiàn) N級聯(lián)動(dòng)效果(兩種實(shí)現(xiàn)方式)

    這篇文章主要介紹了MyBatis之自查詢使用遞歸實(shí)現(xiàn) N級聯(lián)動(dòng)效果,本文給大家分享兩種實(shí)現(xiàn)方式,需要的的朋友參考下吧
    2017-07-07
  • Mybatis?SqlSession案例詳解

    Mybatis?SqlSession案例詳解

    這篇文章主要介紹了Mybatis?SqlSession詳解,本文我們講了如何創(chuàng)建SqlSession的幾個(gè)步驟,最后我們獲得一個(gè)DefaultSqlSession對象,里面包含了執(zhí)行器Executor和配置對象Configuration,需要的朋友可以參考下
    2023-04-04
  • MyBatis在mapper中傳遞參數(shù)的四種方式

    MyBatis在mapper中傳遞參數(shù)的四種方式

    MyBatis是一個(gè)持久層框架,它提供了一種將數(shù)據(jù)庫操作與Java對象之間的映射關(guān)系進(jìn)行配置的方式,在MyBatis中,Mapper是用于定義數(shù)據(jù)庫操作的接口,而參數(shù)傳遞則是通過Mapper接口的方法來實(shí)現(xiàn)的,本文給大家介紹了MyBatis在mapper中傳遞參數(shù)的四種方式,需要的朋友可以參考下
    2024-03-03
  • Spring如何通過@Lazy注解解決構(gòu)造方法循環(huán)依賴問題

    Spring如何通過@Lazy注解解決構(gòu)造方法循環(huán)依賴問題

    循環(huán)依賴其實(shí)就是循環(huán)引用,也就是兩個(gè)或則兩個(gè)以上的bean互相持有對方,最終形成閉環(huán),這篇文章主要給大家介紹了關(guān)于Spring如何通過@Lazy注解解決構(gòu)造方法循環(huán)依賴問題的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • Mybatis中TypeAliasRegistry的作用及使用方法

    Mybatis中TypeAliasRegistry的作用及使用方法

    Mybatis中的TypeAliasRegistry是一個(gè)類型別名注冊表,它的作用是為Java類型建立別名,使得在Mybatis配置文件中可以使用別名來代替完整的Java類型名。使用TypeAliasRegistry可以簡化Mybatis配置文件的編寫,提高配置文件的可讀性和可維護(hù)性
    2023-05-05
  • 詳解用java描述矩陣求逆的算法

    詳解用java描述矩陣求逆的算法

    這篇文章主要介紹了用java描述矩陣求逆的算法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Java串口通信入門

    Java串口通信入門

    串口通信是一種用于在計(jì)算機(jī)和外部設(shè)備之間進(jìn)行數(shù)據(jù)交換的通信方式,本文主要介紹了Java串口通信入門,并提供一個(gè)簡單的示例來演示如何在Java中進(jìn)行串口通信,感興趣的可以了解一下
    2023-11-11
  • spring 如何將配置信息注入靜態(tài)變量的方法

    spring 如何將配置信息注入靜態(tài)變量的方法

    本篇文章主要介紹了spring 如何將配置信息注入靜態(tài)變量的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • Java?導(dǎo)出?CSV?文件操作詳情

    Java?導(dǎo)出?CSV?文件操作詳情

    這篇文章主要介紹了Java導(dǎo)出CSV文件操作詳情,文章通過導(dǎo)入坐標(biāo)展開詳細(xì)內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08

最新評論

泰来县| 肃南| 东乌| 顺义区| 台中县| 临朐县| 乌兰察布市| 聂拉木县| 夏邑县| 昌平区| 武功县| 缙云县| 自治县| 门源| 成安县| 安远县| 巨鹿县| 瑞金市| 海门市| 九江县| 西林县| 陇南市| 广西| 扎赉特旗| 云和县| 桦甸市| 龙陵县| 凤冈县| 德钦县| 丹江口市| 襄城县| 郯城县| 通化县| 金昌市| 周至县| 美姑县| 兴业县| 玛多县| 梁平县| 海阳市| 闻喜县|