spring容器&classLoader
spring通過一個容器的概念,引入父子容器結構,實現bean的隔離&繼承結構。
這種模式在很多場合都有類似的設計,比如Java的classloader機制,OSGi的bundle機制等。
這種機制的優勢,在于將對象的作用范圍進行約束。在復雜環境下,可以通過限定作用范圍使得有沖突的內容和諧共存。
接下來從多個角度闡述對比這幾個方面共同點&差異之處。
隔離
spring通過容器的繼承關系,結合尋找bean的方式實現這個隔離性。在尋找bean時,是先從當前容器尋找,找不到再從父容器中尋找,然后逐層往上尋找直至找到或者到最頂層。
一般常用的容器類有,BeanFactory,AnnotationConfigApplicationContext。
Jvm的classloader一般有3級,且按順序進行加載。分別是:
Bootstrap Classloader
加載核心類庫,比如rt.jar, resources.jar等。
Extention Classloader
加載擴展目錄下的jar包與class。
AppClassloader
加載當前應用classpath下的所有類。
這個多級classloader和父子容器的概念非常相似,父層級在子層級之前初始化,尋找資源時,優先從子層級的緩存開始,然后逐層往上委派,然后再從上往下尋找下來。
OSGi則在這個概念上更進一步,其bundle是一個獨立的classloader,其賦予這個classloader上承載的bundle有動態裝載卸載的能力,進而賦予業務動態更新業務邏輯的能力。其通過導入導出package控制邏輯可見性,通過classloader的委派加載模式進行業務class的JVM內共享。
這種模式在目前的微服務體系下,顯得過于復雜。但是其思想還是可以學習的,動態能力在jvm內容易出一些資源,可見性,穩定性等問題,這些問題很難有合適的解決方案;在jvm外則就是一致性與可靠性相關的問題,這些問題相對有合適的解決方案,擴展性也更佳。
繼承
spring多級容器嵌套繼承后,尋找bean時,可優先從當前容器尋找,找不到再逐層上升到父容器尋找。
jvm的classloader也有繼承結構,appclassloader的父默認就是extClassloader,默認創建的classloader的父都是appClassloader。加載class時,會基于雙親委托的模式進行尋找。先查看當前classloader的緩存是否有,沒有則委托父classloader進行加載,然后遞歸這個流程往上到bootstrap classloader,如果找到了,直接返回,如果沒找到,則折返一級一級往下,在每一層級的掃描范圍內進行加載,直到找到或者找不到為止。
OSGi則是在當前bundle所在的classloader中尋找,找不到再根據package從classloader注冊中心篩選出注冊這個package的classloader對應的bundle。然后再委派這個bundle加載這個class。
運行期動態能力
spring的bean一般啟動時就初始化完成了,基本不會搞運行期動態注冊的事情,畢竟IOC已經處理完成的事情,沒辦法再次注入,需要動態能力的都會走其他方式,比如腳本語言,配置中心等。
但是,可以基于BeanFactory的生命周期管理,動態維護一個Spring容器,基于這個容器實現動態能力。這個就有點類似OSGi,但是因為不涉及跨classloader,復雜度能低很多。
classLoader允許運行期動態裝卸載class,一般在動態代理,動態腳本更新等場合用的比較多。
OSGi,按bundle更新的,這個可以做到隨時更新,但是設計&開發的復雜度很高,使用比較復雜,用好很難。
參考資料:https://blog.csdn.net/briblue/article/details/54973413
總結
以上是生活随笔為你收集整理的spring容器&classLoader的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运行在Docker里的SpringBoo
- 下一篇: Dockerfile里的VOLUMES关