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

SpringBoot中Filter?bean如何添加到Servlet容器

 更新時(shí)間:2023年08月04日 15:06:32   作者:yagefuma  
這篇文章主要介紹了SpringBoot中Filter bean是怎么被添加到Servlet容器中的,本文分步驟結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

對(duì)于Spring Boot的IOC容器——ServletWebServerApplicationContext,其中的Filter bean,每個(gè)Filter bean都會(huì)被獨(dú)立的注冊(cè)成為Servlet的Filter。大概的注冊(cè)過(guò)程分成2步:

  • IOC容器——ServletWebServerApplicationContext將Filter接口的實(shí)現(xiàn)類(lèi)封裝成FilterRegistrationBean,放到ServletContextInitializerBeans實(shí)例的成員變量initializers變量(LinkedMultiValueMap)中
  • Spring 容器(ServletWebServerApplicationContext)從ServletContextInitializerBeans實(shí)例的成員變量initializers變量(LinkedMultiValueMap),中獲取所有的ServletContextInitializer實(shí)現(xiàn)類(lèi),調(diào)用它們的onStartUp函數(shù),F(xiàn)ilterRegistrationBean的onStartup函數(shù)就是在調(diào)用ServletContext的addFilter函數(shù)向Servlet添加Filter

1. IOC容器——ServletWebServerApplicationContext將Filter接口的實(shí)現(xiàn)類(lèi)封裝成FilterRegistrationBean,放到ServletContextInitializerBeans實(shí)例的成員變量initializers變量(LinkedMultiValueMap)中

1.Spring容器——ServletWebServerApplicationContext的refresh()函數(shù)被調(diào)用。

protected void onRefresh() {
    super.onRefresh();    
    try {
       createWebServer();    
       }
    catch (Throwable ex) {
       throw new ApplicationContextException("Unable to start web server", ex);   
    }
}

2.ServletWebServerApplicationContext的createWebServer()函數(shù),

  • 在函數(shù)中會(huì)調(diào)用getSelfInitializer()函數(shù)獲取所有的ServletContextInitializer實(shí)例,
  • 而獲取所有的ServletContextInitializer實(shí)例的過(guò)程中,會(huì)查找所有實(shí)現(xiàn)了Filter接口的bean,并注冊(cè)成FilterRegistrationBean(實(shí)現(xiàn)了ServletContextInitializer接口,所以也屬于ServletContextInitializer實(shí)例),
  • 然后把FilterRegistrationBean放到initializers變量(LinkedMultiValueMap)中
private void createWebServer() {
    WebServer webServer = this.webServer;    
    ServletContext servletContext = getServletContext();    
    if (webServer == null && servletContext == null) {
       StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");       
       ServletWebServerFactory factory = getWebServerFactory();       
       createWebServer.tag("factory", factory.getClass().toString());  
       //  getSelfInitializer()函數(shù)中獲取所有ServletContextInitializer實(shí)例,調(diào)用onStartup方法完成注冊(cè)
       this.webServer = factory.getWebServer(getSelfInitializer());
       ......
}
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
    return this::selfInitialize;
    }
private void selfInitialize(ServletContext servletContext) throws ServletException {
    prepareWebApplicationContext(servletContext);    
    registerApplicationScope(servletContext);    
    WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);  
    //   獲取所有ServletContextInitializer實(shí)例,調(diào)用onStartup方法
    for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
       beans.onStartup(servletContext);   
        }
}
// 傳入BeanFactory,new 一個(gè)ServletContextInitializerBeans對(duì)象,這個(gè)對(duì)象實(shí)現(xiàn)了Collection接口,是一個(gè)集合,
// 集合內(nèi)的元素是需要內(nèi)置在Servlet Context上的ServletContextInitializer bean
protected Collection<ServletContextInitializer> getServletContextInitializerBeans() {
    return new ServletContextInitializerBeans(getBeanFactory());
    }

3.ServletContextInitializerBeans的構(gòu)建

public ServletContextInitializerBeans(ListableBeanFactory beanFactory,       Class<? extends ServletContextInitializer>... initializerTypes) {
    this.initializers = new LinkedMultiValueMap<>();    
    this.initializerTypes = (initializerTypes.length != 0) ? Arrays.asList(initializerTypes)
          : Collections.singletonList(ServletContextInitializer.class);    
     // 找直接定義為ServletContextInitializer的bean(比如FilterRegistrationBean),DelegatingFilterProxyRegistrationBean等,
     // 添加到initializers中
    addServletContextInitializerBeans(beanFactory);    
     // 找實(shí)現(xiàn)了Filter接口的bean,將他們封裝成ServletContextInitializer bean(對(duì)于Filter的實(shí)現(xiàn)類(lèi)也就是封裝成FilterRegistrationBean),
     // 添加到initializers中
    addAdaptableBeans(beanFactory);   
    //排序  
    List<ServletContextInitializer> sortedInitializers = this.initializers.values().stream()
          .flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE))
          .collect(Collectors.toList());    
          this.sortedList = Collections.unmodifiableList(sortedInitializers);    
          logMappings(this.initializers);
}
protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
    MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);    
    // 獲取實(shí)現(xiàn)了Servlet接口的bean
    addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig)); 
    // 查找所有實(shí)現(xiàn)了Filter接口的bean,并注冊(cè)成FilterRegistrationBean,
    // 然后把FilterRegistrationBean放到initializers變量(LinkedMultiValueMap)中
    addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());    
    for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {
       addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType,             
                 new ServletListenerRegistrationBeanAdapter());    
       }
}

所以我們可以看到ServletContextInitializerBeans構(gòu)造函數(shù)是怎么構(gòu)造一個(gè)包含
ServletContextInitializer bean集合的:

  • 直接定義為ServletContextInitializer的bean(比如FilterRegistrationBean),
  • DelegatingFilterProxyRegistrationBean等,添加到initializers中
    找實(shí)現(xiàn)了Filter接口的bean,將他們封裝成ServletContextInitializer bean(對(duì)于Filter的實(shí)現(xiàn)類(lèi)也就是封裝成FilterRegistrationBean),添加到initializers中
  • 排序然后一并返回

所以ServletContextInitializerBeans實(shí)例表示的是:一個(gè)從ListableBeanFactory bean容器中獲得的ServletContextInitializer實(shí)例的集合。這個(gè)集合中的每個(gè)元素來(lái)自容器中定義的每個(gè)如下類(lèi)型的bean :

  • 實(shí)現(xiàn)了ServletContextInitializer接口的bean
  • 具體可能以ServletRegistrationBean/FilterRegistrationBean/EventListenerRegistrationBean的形式存在。這些 bean 設(shè)計(jì)的目的是用來(lái)注冊(cè)相應(yīng)的 Servlet/Filter/EventListener bean 到 ServletContext

- **實(shí)現(xiàn)了Servlet/Filter/EventListener接口的 bean**

這些 bean直接以實(shí)現(xiàn)裸的Servlet/Filter/EventListener接口的 bean的形式存在,但是Springboot會(huì)將它們封裝成相應(yīng)的 RegistrationBean(也是ServletContextInitializer ),然后也注冊(cè)到ServletContext。

也就是說(shuō),Spring幫我們將實(shí)現(xiàn)裸的Servlet/Filter/EventListener接口的 bean,封裝成ServletRegistrationBean/FilterRegistrationBean/EventListenerRegistrationBean。

2. Spring 容器(ServletWebServerApplicationContext)從ServletContextInitializerBeans實(shí)例的成員變量initializers變量(LinkedMultiValueMap),中獲取所有的ServletContextInitializer實(shí)現(xiàn)類(lèi),調(diào)用它們的startUp函數(shù),F(xiàn)ilterRegistrationBean的onStartup函數(shù)就是在調(diào)用ServletContext的addFilter函數(shù)向Servlet添加Filter

1.還是要回到上面1.2中的createWebServer()函數(shù)中,這次我們不看getSelfInitializer(),而是看factory.getWebServer(...)函數(shù)。

private void createWebServer() {
    WebServer webServer = this.webServer;    
    ServletContext servletContext = getServletContext();    
    if (webServer == null && servletContext == null) {
       StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");       
       ServletWebServerFactory factory = getWebServerFactory();       
       createWebServer.tag("factory", factory.getClass().toString());  
       //  getSelfInitializer()函數(shù)中獲取所有ServletContextInitializer實(shí)例,調(diào)用onStartup方法完成注冊(cè)
       this.webServer = factory.getWebServer(getSelfInitializer());
       ......
}

2.TomcatServletWebServerFactory的getWebServer(...)函數(shù)

public WebServer getWebServer(ServletContextInitializer... initializers) {
    if (this.disableMBeanRegistry) {
       Registry.disableRegistry();    
    }
    ......
    // 將前面獲取到的所有ServletContextInitializer實(shí)例作為參數(shù),傳下去
    prepareContext(tomcat.getHost(), initializers);    
    return getTomcatWebServer(tomcat);
 }

3.TomcatServletWebServerFactory的prepareContext(...)

protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
    ......
    // 合并一下
    ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);    
    host.addChild(context);   
    // 將前面獲取到的所有ServletContextInitializer實(shí)例作為參數(shù),傳下去 
    configureContext(context, initializersToUse);    
    postProcessContext(context);}

4.tomcatServletWebServerFactory的configureContext(...),創(chuàng)建了TomcatStarter,并將TomcatStarter綁定到Tomcat上,這樣Tomcat啟動(dòng)時(shí)就會(huì)回調(diào)TomcatStarter的onStartup函數(shù)。

protected void configureContext(Context context, ServletContextInitializer[] initializers) {
    // 將前面獲取到的所有ServletContextInitializer實(shí)例作為參數(shù),傳下去 
    TomcatStarter starter = new TomcatStarter(initializers);
    // 下面這一系列操作是將TomcatStarter綁定到Tomcat上,這樣TomcatStarter就會(huì)在Tomcat啟動(dòng)時(shí)被回調(diào)
    if (context instanceof TomcatEmbeddedContext) {
    TomcatEmbeddedContext embeddedContext = (TomcatEmbeddedContext) context;    
    embeddedContext.setStarter(starter);    
    embeddedContext.setFailCtxIfServletStartFails(true);
    }
    context.addServletContainerInitializer(starter, NO_CLASSES);
    ......
}

5.TomcatStarter的startUp函數(shù)被調(diào)用的時(shí)候,就會(huì)變量所有的ServletContextInitializer實(shí)例的onStartup函數(shù),

public void onStartup(Set<Class<?>> classes, ServletContext servletContext) throws ServletException {
    try {
       for (ServletContextInitializer initializer : this.initializers) {
          initializer.onStartup(servletContext);       
          }
    }
    catch (Exception ex) {
       this.startUpException = ex;       
       // Prevent Tomcat from logging and re-throwing when we know we can       
       // deal with it in the main thread, but log for information here.      
       if (logger.isErrorEnabled()) {
          logger.error("Error starting Tomcat context. Exception: " + ex.getClass().getName() + ". Message: "                + ex.getMessage());       
          }
    }
}

6.回顧第一章:“Filter接口的實(shí)現(xiàn)類(lèi)封裝成FilterRegistrationBean”,而FilterRegistrationBean又是ServletContextInitializer接口的實(shí)現(xiàn)類(lèi),所以上面第5步,也會(huì)回調(diào)FilterRegistrationBean的onStartup函數(shù),

//FilterRegistrationBean
public final void onStartup(ServletContext servletContext) throws ServletException {
    String description = getDescription();    
    if (!isEnabled()) {
       logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");       return;    
       }
    // 這里
    register(description, servletContext);
}

7.DynamicRegistrationBean.class

protected final void register(String description, ServletContext servletContext) {
    //這里
    D registration = addRegistration(description, servletContext);    
    if (registration == null) {
       logger.info(StringUtils.capitalize(description) + " was not registered (possibly already registered?)");       
       return;    
       }
    configure(registration);
    }

8.AbstractFilterRegistrationBean.class, 看到?jīng)],最終還是用ServletContext的addFilter函數(shù),向Servlet容器中添加Filter。

protected Dynamic addRegistration(String description, ServletContext servletContext) {
    // getFilter()在FilterRegistrationBean中被實(shí)現(xiàn),返回的就是那個(gè)Filter接口的實(shí)現(xiàn)類(lèi)。
    Filter filter = getFilter();   
    // 將Filter接口的實(shí)現(xiàn)類(lèi)添加到Servlet容器中 
    return servletContext.addFilter(getOrDeduceName(filter), filter);
  }

參考資料

到此這篇關(guān)于SpringBoot中Filter bean是怎么被添加到Servlet容器中的的文章就介紹到這了,更多相關(guān)SpringBoot Filter bean添加到Servlet容器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于maven打包出錯(cuò)的解決方案

    關(guān)于maven打包出錯(cuò)的解決方案

    這篇文章主要介紹了關(guān)于maven打包出錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java中啟動(dòng)jar包的方式匯總

    Java中啟動(dòng)jar包的方式匯總

    Java 命令執(zhí)行 JAR 包是一種常見(jiàn)的應(yīng)用場(chǎng)景,在實(shí)際開(kāi)發(fā)中,我們經(jīng)常需要執(zhí)行 JAR 包文件,那么,如何使用 Java 命令執(zhí)行 JAR 包呢?本文將為大家介紹八種不同的方法,需要的朋友可以參考下
    2025-09-09
  • 深入了解JAVA HASHMAP的死循環(huán)

    深入了解JAVA HASHMAP的死循環(huán)

    HASHMAP基于哈希表的 Map 接口的實(shí)現(xiàn)。此實(shí)現(xiàn)提供所有可選的映射操作,并允許使用 null 值和 null 鍵。(除了非同步和允許使用 null 之外,HashMap 類(lèi)與 Hashtable 大致相同。)下面小編來(lái)帶大家詳細(xì)了解下吧
    2019-06-06
  • spring中自動(dòng)注入注解的實(shí)現(xiàn)方式

    spring中自動(dòng)注入注解的實(shí)現(xiàn)方式

    在Spring框架中,AutowiredAnnotationBeanPostProcessor負(fù)責(zé)處理@Autowired和@Value注解,實(shí)現(xiàn)依賴(lài)注入,首先通過(guò)TypeMappedAnnotations獲取注解,并根據(jù)注解屬性構(gòu)建InjectionMetadata,存入緩存
    2024-09-09
  • java判斷字符串是否為null的四種方式匯總

    java判斷字符串是否為null的四種方式匯總

    這篇文章主要介紹了java判斷字符串是否為null的四種方式匯總,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringSecurityOAuth2 如何自定義token信息

    SpringSecurityOAuth2 如何自定義token信息

    這篇文章主要介紹了SpringSecurityOAuth2 自定義token信息的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java8新特性-Lambda表達(dá)式詳解

    Java8新特性-Lambda表達(dá)式詳解

    Java 8 (又稱(chēng)為 jdk 1.8) 是 Java 語(yǔ)言開(kāi)發(fā)的一個(gè)主要版本。Lambda 表達(dá)式,也可稱(chēng)為閉包,它是推動(dòng) Java 8 發(fā)布的最重要新特性。本文通過(guò)詳細(xì)的代碼示例介紹了Java8新特性感興趣的朋友可以參考一下
    2023-04-04
  • java?springboot中如何讀取配置文件的屬性

    java?springboot中如何讀取配置文件的屬性

    大家好,本篇文章主要講的是java?springboot中如何讀取配置文件的屬性,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • 深入理解Java new String()方法

    深入理解Java new String()方法

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java new String()展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 使用springboot制作博客管理系統(tǒng)

    使用springboot制作博客管理系統(tǒng)

    這篇文章主要介紹了使用springboot制作博客管理系統(tǒng),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)springboot的小伙伴有很大的幫助,感興趣的小伙伴可以參考一下
    2021-08-08

最新評(píng)論

吉安县| 长葛市| 柳林县| 正镶白旗| 仲巴县| 泰州市| 大新县| 区。| 文化| 花莲县| 长白| 阿勒泰市| 修文县| 乌拉特中旗| 武强县| 湖南省| 岳普湖县| 黄平县| 和政县| 庆阳市| 蓬莱市| 定日县| 肃北| 介休市| 西藏| 年辖:市辖区| 大余县| 门头沟区| 沛县| 垣曲县| 淮北市| 甘南县| 星子县| 阿鲁科尔沁旗| 泸州市| 荥经县| 上栗县| 乌鲁木齐县| 孙吴县| 安丘市| 定结县|