1.BeanFactory
它是spring中IOC容器实现的一个最基础的接口, 里面定义了许多管理Bean的方法, 例如获取实例, 判断等方法
![](https://i-blog.csdnimg.cn/blog_migrate/7b2e8b8a724d67398d6ebfe85fc08a48.png)
它里面还有许多的实现类, 每一个实现类都有具体的功能(单一职责原则), 其中DefaultListableBeanFactory是spring底层用来生产Bean的实现类工厂.
2.ApplicationContext
间接继承了BeanFactory, 它们都可以当做 Spring的容器,Spring 容器是生成 Bean 实例的工厂,并管理容器中的 Bean。
![](https://i-blog.csdnimg.cn/blog_migrate/d2e5675f3584c9d0151e997c48aed671.png)
3.区别
1.BeanFactory是面向spring本身的, 比较底层, 是spring中比较原始的工厂, 不支持AOP, Web等插件, 而ApplicationContext不但包含了前者所有的功能, 还扩展了许多新的功能, 还支持spring中的各种插件
2.BeanFactory采用的是延迟加载形式注入bean的, 只有在使用到某个bean时(getBean()), 才对bean进行实例化, 是的我们不能发现一些配置上的问题, 而后者是在程序启动时就实例化了所有的bean, 这样我们在容器启动时就可以发现一些spring中的配置错误问题, 相对于BeanFactory唯一的不足就是比较占用内存空间, 当Bean创建的较多的时, 就会出现程序启动较慢的问题.
4.Bean的生命周期
spring的生命周期可以分为5个阶段:
1.创建实例化对象 Instantiation
2.属性赋值 Populate
3.初始化 Initialization
4.放入容器中使用
5.销毁 Destruction
在初始化的过程中, 3.1如果Bean 实现 BeanNameAware 执行 setBeanName
3.2 如果 Bean 实现 BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext 对象.
3.3 如果存在类实现 BeanPostProcessor(AOP) ,执行postProcessBeforeInitialization
3.4 如果 Bean 实现 InitializingBean 执行 afterPropertiesSet如果配置了自己的初始化方法<bean init-method="init">
3.5 如果存在类实现 BeanPostProcessor(AOP) ,执行postProcessAfterInitialization
5.1销毁 如果 Bean 实现 DisposableBean 执行 destroy
如果配置了自己的销毁方法<bean destroy-method="customerDestroy">指定销毁方法 customerDestroy.
![](https://i-blog.csdnimg.cn/blog_migrate/7b09afbae22e9a69b13a0ba917a56bee.png)
5.Bean的线程安全问题
spring容器本身并没有提供Bean的线程安全策略, 要结合具体scope的Bean的情况.
Spring 的 bean 作用域(scope)类型
1、singleton:单例,默认作用域, 可以使用ThreadLocal为每个请求创建一个变量副本
2、prototype:原型,每次创建一个新对象。
原型 Bean:
对于原型 Bean,每次创建一个新对象,也就是线程之间并不存在 Bean 共享,自然是不会有线程安全的问题。
单例 Bean:
对于单例 Bean,所有线程都共享一个单例实例 Bean,因此是存在资源的竞争。
Bean 又分为有状态就是有数据存储功能(例如包含成员变量), 无状态就是不会保存数据
如果单例 Bean,是一个无状态 Bean,也就是线程中的操作不会对 Bean 的成员执行查询以外的操作,那么这个单例 Bean 是线程安全的。比如 Spring mvc 的 Controller、Service、Dao 等,这些 Bean 大多是无状态的,只关注于方法本身。
但是如果 Bean 是有状态的 那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变 bean 的作用域 把 "singleton"改为‘protopyte’ 这样每次请求Bean 就相当于是 new Bean() 这样就可以保证线程的安全了。
controller、service 和 dao 层本身并不是线程安全的,只是如果只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工作内存,是安全的。
测试证明单例 bean 不是线程安全的
![](https://i-blog.csdnimg.cn/blog_migrate/c8c95346eac06efcab557e34b1ad628c.png)