Spring详解,底层原理深入探究(2)
1.探究BeanFactory 和 ApplicationContext
1.简介
在 spring 容器中,BeanFactory 接口是 IOC 容器要实现的最基础的接口,定义 了管理 bean 的最基本的方法,例如获取实例、基本的判断等
ApplicationContext也间接继承了BeanFactory,如果说BeanFactory是Sping 的心脏,那么 ApplicationContext 就是完整的身躯了。它们都可以当做 Spring 的容器,Spring 容器是生成 Bean 实例的工厂,并管理容器中的
2.区别:
1.BeanFactory 是 Spring 中比较原始的 Factory,它不支持 AOP、Web 等 Spring 插件. 而 ApplicationContext 不仅包含了 BeanFactory 的所有功能,还支持 Spring 的各种插件,还以一种面向框架的方式工作以及对上下文进行分层和实现 继承。
2.BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;而 ApplicationContext 面向使用 Spring 的开发者,相比 BeanFactory 提供 了更多面向实际应用的功能,几乎所有场合都可以直接使用 ApplicationContex。
3.实现ApplicationContext 接口的方式会在spring 启动时初始化所有的单例 bean,也可以为 bean 设置 lazy-init 属性为 true. 实BeanFactory的接口不会启动创建单例Bean而是在getBeans时创建
2.spring创建Bean的过程
1.过程
1.创建一个Bean的实例
2.注入Bean的属性
3.初始化Bean
4.将其放入容器并使用
5.销毁
!!!Spring创建的对象的属性的引用不为空
3.Spring创建的单例bean线程安全吗
如果@scope没有设置‘protopyte’,Spring创建的bean默认为单例模式
单例的bean会存在线程安全问题
非单例的线程安全
单例Bean:
zhongzhi如果对象中含有有数据储存功能的变量(例如:对象含有int count=1这个变量,如果A线程更改了变量,B线程的这个变量也会被更改。),所有的线程共享一个对象,会出现线程安全的问题
如果线程中只含有无状态变量,例如(UserDao userDao ,menuDao menuDao),由于这类对象只关心方法没有存储具体的值,所以不存在线程安全的问题
4.Bean 循环依赖
`public class A{
private B b;
}
public class B{
private A a;
}`
有这样的两个类互相关联;按照传统的方法
`A a =new A();
B b=new B();
a.b=b;
b.a=a;`
两个对象就创建好了
但引入了Spring框架以后,为了解耦对象交给Spring框架创建,则会产生问题
创建A对象的时候需要B对象
那么去创建B对象,创建B对象又需要A造成死循环
Spring框架针对这种问题设出三层缓存
1.一级缓存缓存的是实例化,注入属性,并初始化完成的对象
2.二级缓存缓存的数据是,实例化的bean对象
3.三级缓存缓存的是bean 创建工厂,以便于后面扩展有机 会创建代理对象。
那么这个问题迎刃而解
1.创建A对象的实例
2.把A对象的实例存入二级缓存
3.给A注入B对象的实例
1.去二级缓存找有没有B对象的实例
2.没有
3.创建B对象的实例
4.将B对象的实例存入二级缓存
5.给B对象注入A对象
6.去二级缓存找
7.找到了二级缓存中A对象的实例
8注入
9初始化
10存入一级缓存
4.去二级缓存找B对象的实例
5.找到了
6.注入
7.初始化
8.存入一级缓存
创建完成
难点问题:已经把A对象注入给了B,后面再注入A对象的属性,那么B对象中的A对象会有B对象这个属性吗?
解答;会有,注入B对象中的A对象只是一个引用地址。