深入理解Spring系列之十三:IntrospectorCleanupListener解析

Introspector作用及影響

在分析IntrospectorCleanupListener之前,先了解一下Introspector。Introspector是JDK中java.beans包下的類,它為目標JavaBean提供了一種了解原類方法、屬性和事件的標準方法。通俗的說,就是可以通過Introspector構建一個BeanInfo對象,而這個BeanInfo對象中包含了目標類中的屬性、方法和事件的描述信息,然后可以使用這個BeanInfo對象對目標對象進行相關操作。

下面看一個簡單的示例會很容易明白。為了簡單,Student類中只有一個name屬性。


結果輸出:Student{name='張三'}

通過查看Introspector.getBeanInfo方法的源碼會發現,Introspector在構建一個BeanInfo對象的時候,會將構建的BeanInfo對象和原類緩存到一個Map中,源碼如下。

通過上的代碼可以得出,Introspector間接持有了BeanInfo的強引用。如果使用Introspector操作了很多類,那么Introspector將間接持有這些BeanInfo的強引用。在發生垃圾收集的時候,檢測到這些BeanInfo存在引用鏈,則這些類和對應的類加載器將不會被垃圾收集器回收,進而導致內存泄漏。所以,為了解決這個問題,在使用Introspector操作完成后,調用Introspector類的flushCaches方法清除緩存。

通過上面的代碼會發現,清除的時候是清空了整個緩存,因為沒有很好的辦法來確定每個緩存是屬于哪個應用的,所以清除的時候會清除所有應用的緩存。

IntrospectorCleanupListener解析

上面分析了Introspector的作用和影響,那IntrospectorCleanupListener和Introspector有什么關系呢?
IntrospectorCleanupListener是spring-web jar中的類,源碼如下。

IntrospectorCleanupListener實現了ServletContextListener接口,也就是說,在web容器初始化(準確的說是在filters或servlets初始化之前)的時候會執行contextInitialized方法,在ServletContext銷毀(準確的說是在filters和servlets銷毀之后)的時候會執行contextDestroyed方法。從圖中contextDestroyed方法,可以看到在銷毀ServletContext的時候調用了Introspector.flushCaches方法,清空了對應緩存。IntrospectorCleanupListener中為什么要這么做?難道是Spring使用Introspector操作后沒有清空對應緩存?查看IntrospectorCleanupListener類的源碼,會發現有這樣一段標注。

大意是說,在使用Spring本身的時候并不需要使用此監聽器,因為Spring自己的內部機制會立即清空對應的緩存。雖然,Spring本身不存在這樣的問題,但是如果和其它框架結合使用,而其它框架有這個問題,如Struts、Quartz等,那就需要配置這個監聽器,在銷毀ServletContext的時候清空對應緩存。

有一點需要注意的是,像這樣一個簡單的Introspector內存泄漏將會導致整個應用的類加載器不會被垃圾收集器回收,如果有內存泄漏的問題,可以考慮此因素。

配置IntrospectorCleanupListener

在以往的工作經歷中,多次看到在web.xml中將IntrospectorCleanupListener配置成非第一個listener。

其實,看過源碼的都知道,官方的表述是必須將此監聽器配置成web.xml中的第一個listener,才能在合適的時間發揮最有效的作用。

原因其實很簡單,在Servlet3.0規范之前,監聽器的調用是隨機的,而從Servlet3.0開始,監聽器的調用順序是根據其在web.xml中配置的順序,并且實現ServletContextListener的監聽器,contextInitialized方法調用順序是按照在web.xml中配置的順序正序依次執行,而contextDestroyed方法的調用順序是按照在web.xml中配置的順序逆序依次執行。所以,如果IntrospectorCleanupListener被配置成了第一個listener,那么它的contextDestroyed方法將最后一個執行,將發揮最有效的清除作用;而如果不是,那么可能會殘留未被清除的緩存。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,908評論 18 139
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,948評論 6 342
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,366評論 11 349
  • 日月更替,四季輪回,眼看五月即將過去,馬上就要進入啤酒的銷售旺季,回顧過去幾個月的工作過程中的經驗教訓,期盼未來的...
    遺忘_c5b3閱讀 1,093評論 0 0
  • 其實,一直以來我都用:“相見爭如不見,有情何似無情。”來說服自己不去想你、不再沉迷在“虛擬”的世界中。但無意間我看...
    最愛海綿寶寶閱讀 356評論 0 0