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

posted @ 2020-07-20 11:52  飞昂之雪  阅读(1456)  评论(0编辑  收藏  举报