IoC理念
IOC不是一种技术,是一种思想
- 原来在使用对象的时候,我们的做法都是去自己创建一个对象出来,在类的构造函数中添加依赖类,可以用这么个例子举例:我们的新家装修的时候需要家具,我们自己去打造出来。
- 而IoC就是为了简化这个问题,我们不需要自己去造家具,我们让别人为我们服务 控制反转控制反转,即:“Don’t call us,we will call you”。
- 总结:IoC就是将我们主动创建对象的权利交给容器,让容器来替我们做这些事情,替我们创建对象和管理对象之间的关系,我们需要做的只是配置好配置文件。
IoC依赖注入的几种方式
- 构造方法注入:IOC会检查被注入对象的构造方法,由此来确定需要的依赖对象,进而对其注入到相应的对象中。
<bean id="userService" class="com.shuaiwen.service.UserService">
<constructor-arg ref="userDao"></constructor-arg>
</bean>
<bean id="userDao" class="com.shuaiwen.dao.UserDao"></bean> -->
- setter方法注入:普通Java对象中,我们进行属性设置的时候,基本通过调用其set方法进行赋值,而IoC中也同理,在xml文件中设置属性的值
<bean id="userService" class="com.shuaiwen.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.shuaiwen.dao.UserDao"></bean>
- 自动注入:通过注解,使用byType、byName、constructor三种方式进行注入
- 接口注入:接口注入基本处于”退役状态“,因为通过这种方法,要注入依赖对象,就必须提实现一个接口,提供一个方法来注入对象,这样会导致增加很多不必要的接口,具有比较强的侵入性,仅供了解。
创建实体Bean的几种方式
- 基于class构建:
<bean class="com.xyz.spring.Hello"></bean>
这种创建方式比较常规,在Spring底层通过class的属性反射进行构建,但是需要构造函数是无参 - 基于构造方法构建:
- 静态工厂方法构建:
<bean class="com.xyz.spring.Hello" factory-method="build"><constructor-argname="xxx" value="xxx"/> </bean>
- 基于FactoryBean创建:在方法中实现 FactoryBean 接口,重写getObject()方法,在xml配置相应属性。
IOC如何管理对象之间的依赖关系
- 直接编码:将被注入对象和依赖对象注册到容器中,当需要对象实例的时候直接从容器中返回
- 配置文件: 在配置文件中声明对象之间的依赖关系和信息
- 元数据方式
BeanFactory
IoC容器有两种实现容器类型:BeanFactory和ApplicationContext。
BeanFactory是基础类型的IoC容器,默认使用懒加载的方式进行初始化。只有在客户端需要某个受管对象时,才会初始化和依赖注入这个对象。
这种方法容器启动速度快,需要的资源有限,但不能及时发现问题。
BeanFactory怎么读取xml文件内容?(解决依赖关系的一种方式)
通过BeanDefinitionReader读取xml文件并解析,将解析后的文件内容映射到BeanDefinition(BeanDefinition主要描述Bean的定义),
将xml中的id和对应的BeanDefinition注册到BeanDefinitionRegistry(BeanDefinitionRegistry主要存放Bean的id和BeanDefinition,可以看做是把id作为key)
BeanFactory获取bean的过程
- 客户端执行getBean()方法后,BeanFactory执行对应的doGetBean()方法
- 首先从缓存中获取是否存在单例Bean,如果存在则返回。
- 如果不存在,先判断是需要创建单例对象还是多例对象,Singleton or prototype?
- 如果是单例Bean,先创建Bean,然后将其加入到缓存中
- 如果是多例Bean,直接创建Bean。
- 再通过反射创建Bean实例并返回
Bean的scope
典型的scope:
- Singleton:Singleton类型的bean,在一个容器中只存在一个共享实例,从第一次被请求开始,只要容器不销毁,这个bean就会一直存在。
- prototype:Bean的scope声明为Prototype时,容器每次接到对象的请求,都会重新去创建一个Bean实例返回,而且将实例返回之后,容器就不再拥有实例的引用了!! 需要请求方自己去负责后继实例的生命周期的管理工作。
spring2.0后新增的:
- request:为每个Http请求创建一个全新的对象,请求结束对象也就被销毁了
- session
- global session
BeanFactoryPostProcessor
BeanFactoryPostProcessor机制作用在【容器启动时】,提供了在bean【实例化之前】BeanDifinition的机会
Bean的生命周期
- 实例化bean对象,调用构造方法
- 设置bean对象的属性,调用相应的set方法
- 检查实现了哪些Aware接口,进行相关的接口方法设置,比如实现了:BeanNameAware接口,就调用setBeanName方法 来设置bean的name
- 如果Bean实现了BeanPostProcessor接口,进行BeanPostProcessor的前置处理,Spring就将调用他们的postProcessBeforeInitialization()方法进行预初始化,作用是在Bean实例创建成功后对进行增强处理。
- 检查是否实现InitializingBean接口,如果有就调用afterPropertiesSet()方法进行调整,在Bean的全部属性设置成功后执行的初始化方法。
- 如果 Bean 在配置⽂件中的定义包含 init-method 属性,执⾏指定的⽅法。
- 如果Bean实现了BeanPostProcessor接口,进行BeanPostProcessor的前置处理, Spring就将调用他们的postProcessorAfterInitialization()方法进行预初始化,作用和4一样。
- 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
- 如果实现DisposableBean,就调用接口指定方法。
- 如果 Bean 在配置⽂件中的定义包含destroy-method 属性,执⾏配置的指定的⽅法。
.