一、核心概念
- IOC:控制翻转
一般而言,实现某个功能都需要两个对象协作完成,当A对象需要B对象时。传统的做法是A对象通过new B(),来显示的获取B对象。这种做法会高度耦合,由具体的对象自行维护依赖关系。当系统中依赖关系复杂时,修改依赖关系是个非常沉重的过程。使用IOC容器,对象并不自行维护依赖关系,而是由容器来负责依赖对象的创建、初始化、销毁。
将“对象--对象”的依赖模式,转换为“对象--容器--对象”的依赖模式。当需要修改依赖关系时,只要修改容器中相应的被依赖对象即可,调用端对象不需要修改任何代码。从而达到松耦合。何为控制翻转:对象并不管理自己的依赖关系,由容器负责管理。
- DI(依赖注入)
从另外一个角度命名spring容器。IOC注重于将对依赖的管理控制交给容器。DI则是将关注点放在容器为对象注入所依赖的组建的过程。
初始化对象时,由容器将依赖的对象通过某种方式注入进来(setter、构造器)
二、基础组件
- 1、BeanFactory
spring底层容器,定义了最基本的容器功能,注意区分FactoryBean
- 2、ApplicationContext
扩展于BeanFactory,拥有更丰富的功能。例如:添加事件发布机制、父子级容器,一般都是直接使用ApplicationContext。
- 3、Resource
bean配置文件,一般为xml文件。可以理解为保存bean信息的文件。
- 4、BeanDefinition
beandifinition定义了bean的基本信息,根据它来创造bean
三、先来一发
- 1、主程序
- 2、配置文件
- 3、运行结果
通过运行结果很容易发现我们配置在xml中的kobe对象,确实起作用了。那么请问
1:配置的<bean>是怎么转换成Student对象的呢?
2:配置的value值是怎样设置到student中的呢?
3:spring容器怎样管理该对象的呢?
请带着这些问题继续往下看
四、容器启动步骤
1、资源定位:找到配置文件
2、BeanDefinition载入和解析
3、BeanDefinition注册
4、bean的实例化和依赖注入
1、BeanDefinition载入、解析、注册
1、找到配置文件Resource。
2、将配置文件解析成BeanDefinition
3、将BeanDefinition向Map中注册 Map<name,beandefinition>
通过上述三个步骤我们将配置在配置文件中的<bean/>节点,全部封装到上述的Map<name,beandefinition>中。为后续的getBean()打下了基础。
这个过程大概可以理解为,
1:找到原材料
2:把原材料装进容器里
2、bean的实例化和依赖注入
此过程由getBean()方法触发
创造 bean
实现依赖注入
此过程根据上述的BeanDefition,
1:通过反射或者Cglib的方式创造bean
2:根据配置的依赖将所需要的bean注入进来,此过程会递归调用getBean()方法。
3:根据bean的scope决定是否缓存该Bean,一般情况为单例。容器会缓存该对象。
这个过程大概可以理解为
将原材料进行加工,创造可以直接利用的产品。
到此,spring容器就可以对外提供服务了。
五、总结
容器启动的过程可以分为2大步
1:获取、解析、注册配置信息,将配置的文件信息转换Map<name,beanDefinition>
2:根据上述的Map<name,beanDefinition>去实例化bean,并完成以来注入
以上是根据传统的xml形式配置Bean,现在很少用,现在用的比较多的是注解和javaConfig的形式配置,但换汤不换药,只是容器获取Map<name,beanDefition>的过程变了而已。这也是容器容器初始化步骤细化的一个好处。易于扩展。
spring容器的启动过程由spring框架封装好了,并不需要我们手动编程,但理解其启动原理,更有利于我们对spring的使用和扩展。笔者只是粗略的了解了下大概的流程,如有不当之处,欢迎留言指教。