微信号:javajidi_com

介绍:专注Java与Web技术的研究;分享有价值的技术;经验;关注程序员的发展.

spring IOC容器内部工作机制

2015-04-16 19:20 Java技术

Spring容器像一台构造精妙的机器,我们通过配置文件向机器传达控制信息,机器就能够按照设定的模式进行工作。如果我们将Spring容器比喻为一辆汽车,可以将BeanFactory看成汽车的发动机,而ApplicationContext则是整辆汽车,它不但包括发动机,还包括离合器、变速器以及底盘、车身、电气设备等其他组件。在ApplicationContext内,各个组件按部就班、有条不紊地完成汽车的各项功能。

Spring的AbstractApplicationContext是ApplicationContext抽象实现类,该抽象类的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程,这些处理过程清晰刻画了Spnng容器启动时所执行的各项操作。
//初始化bean工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();

//调用工厂后处理器
invokeBeanFactoryPostProcessors();

//注册bean后处理器
registerBeanPostProcessors();

//初始化消息源
initMessageSource();

//初始化应用上下文事件广播器
initAppIicationEventMulticaster();

//初始化其他特殊的bean,由具体子类实现
onRefresh();

//注册事件监听器
registerListeners();

//初始化所有单实例bean
finishBeanFactorylnitiallzation(beanFactory);

//完成刷新并发布容器刷新事件
finishRefresh();

1.初始化BeanFactory:根据配置文件实例化BeanFactory, getBeanFactory()方法由县体子类实现。在这一步里,Spring将配置文件的信息装入到容器的Bean定义注册表(BeanDefinitionRegistry)中,但此时Bean还未初始化;
2.调用工厂后处理器:根据反射机制从BeanDefinitionRegistry中找出所有BeanFactoryPostProcessor类型的Bean,并调用其postProcessBeanFactory()接口方法;
3.注册Bean后处理器:根据反射机制从BeanDefinitionRegistry中找出所有BeanPostProcessor类型的Bean,并将它们注册到容器Bean后处理器的注册表中:
4.初始化消息源:初始化容器的国际化信息资源;
5.初始化应用上下文事件广播器;
6.初始化其他特殊的Bean:这是一个钩子方法,子类可以借助这个方法执行一些特殊的操作:如AbstractRefreshableWebApplicationContext就使用该方法执行初始化ThemeSource的操作:
7.注册事件监听器;
8.初始化所有单实例的Bean,初始化Bean后,将它们放入Spring容器的缓存中;
9.发布上下文刷新事件:创建上下文刷新事件,事件广播器负责将些事件广播到每
个注册的事件监听器中。

spring协调多个组件共同完成这个复杂的工作流程,从加载配置文件到创建出一个完整bean大概会有以下流程。

1.ResourceLoader从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件的资源;
2.BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中每一个<bean>解析成一个BeanDefinition对象,并保存到BeanDefinitioRegistry中。
3.容器扫描BeanDefinitionRegistry中的BeanDefinition,使用Java的反射机制自动识别出Bean工厂后处理器(实现BeanFactoryPostProcessor接口)的Bean,然后调用这些Bean工厂后处理器对BeanDefinitionRegistry中的BeanDefinition进行加工处理。主要完成以下两项工作:
1)对使用到占位符的<bean>元素标签进行解析,得到最终的配置值,这意味对一些半成品式的BeanDefinition对象进行加工处理并得到成品的BeanDefinition对象;
2)对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过Java反射机制找出所有属性编辑器的Bean(实现java.beans.PropertyEditor按口的Bean),并自动将它们注册到Spring容器的属性编辑器注册表中(PropertEditorRegistry);
4.Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,并调用InstantiationStrategy着手进行Bean实例化的工作;
5.在实例化Bean时,Spring容器使用BeanWrapper对Bean进行封装,BeanWrapper提供了很多以Java反射机制操作Bean的方法,它将结合该Bean的BeanDefinition以及容器中属性编辑器,完成Bean属性的设置工作;
6.利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean)对已经完成属性设置工作的Bean进行后续加工,直接装配出一个准备就绪的Bean。

Spring容器堪称一部设计精密的机器,其内部拥有众多的组件和装置。Spring的高明之处在于,它使用众多接口描绘出了所有装置的蓝图,构建好Spring的骨架,继而通过继承体系层层推演,不断丰富,最终让Spring成为有血有肉的完整的框架。所以查看
Spring框架的源码时,有两条清晰可见的脉络:
1)接口层描述了容器的重要组件及组件间的协作关系;
2)继承体系逐步实现组件的各项功能。
接口层清晰地勾勒出Spring框架的高层功能,框架脉络呼之欲出。有了接口层抽象的描述后,不但Spring自己可以提供具体的实现,任何第三方组织也可以提供不同实现,可以说Spring完善的接口层使框架的扩展性得到了很好的保证。纵向继承体系的逐步扩展分步骤地实现框架的功能,这种实现方案保证了框架功能不会堆积在某些类的身上,造成过重的代码逻辑负载,框架的复杂度被完美地分解开了。
spring框架的源码是程序设计的艺术表现,通过它你能深切的感受到设计的美妙,作为技术进阶的方式,非常值得好好阅读

 
Java技术 更多文章 准备进入码农行业?你准备好了吗 Java是怎样运行的,你敢说真的知道? Java:怎样理解byte的最大值是2^7-1 交换思想在程序设计中的应用 Java:线程初识
猜您喜欢 【R每日一贴】R多元线性回归? 微信支付开发信息同步(一) 揭秘在安卓平台上奇慢无比的 ClassLoader.getResourceAsStream 不要让华为跑了?华为回应:没打算跑。但感觉也差不多 Python将迁移到GitHub