知识点复习39 Spring 01

spring中beanFactory和ApplicationContext的联系和区别

总体上讲:

        BeanFactory是Spring中最基本、通用的工厂,这里的工厂,其不仅仅是构造实例,它可以创建并管理各种类的对象,即是Spring IOC容器体系结构的基本接口,其与其子接口便构成了Spring IOC容器的体系结构(如下图:IOC容器主要接口关系图)。所以不要把它理解成常规意义的简单工厂,也可以把它称为Sring容器。

        而ApplicationContext也是一个Spring容器,它是由BeanFactory接口派生而来,因而提供BeanFactory所有的功能,此外它还扩展了BeanFactory的功能,提供了更多的高级功能:

 MessageSource, 提供国际化的消息访问  
资源访问,如URL和文件  
事件传播  
载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。

 

所以联系上它们本身都是Spring提供的接口,它们都和其子接口构成了Spring IOC的容器,我们一般都称他们为Spring容器。其中BeanFactory是Spring框架的基础设施,面向Spring本身,其提供基本的功能,如:getBean(),;ApplicationContext是建立在它之上,面向使用者,扩展了更多面向应用的功能,更易于创建实际应用,实际也基本使用它。

    区别上:由上述可知他们提供的功能是有不同的,体系结构、用途等有所不同。另外他们在初始化时有一个重大的区别:BeanFactroy初始化容器时,并未初始化Bean,直到第一次在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化(延迟加载),这样的话,我们就不能在初始化容器时发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,就一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 
 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Spring 注入循环依赖的解决

如何理解“依赖”呢,在Spring中有:

  • 构造器循环依赖

  • field属性注入循环依赖

总结:Spring创建好了BeanDefinition之后呢,会开始实例化Bean,并且对Bean的依赖属性进行填充。实例化时底层使用了CGLIB或Java反射技术。上图中instantiateBean核PupulateBean方法很重要!

循环依赖问题分析

我们先总结一下之前的结论:

1、构造器注入和prototype类型的field注入发生循环依赖时都无法初始化

2、field注入单例的bean时,尽管有循环依赖,但bean仍然可以被成功初始化

针对这几个结论,提出问题

  1. 单例的设值注入bean是如何解决循环依赖问题呢?如果A中注入了B,那么他们初始化的顺序是什么样子的?

  2. 为什么prototype类型的和构造器类型的Spring无法解决循环依赖呢?

前面三个Map,我们称为单例初始化的三级缓存,理解这个问题,我们目前只需关注“三级”,也就是singletonFactories

分析:

对于问题1,单例的设值注入,如果A中注入了B,B应该是A中的一个属性,那么猜想应该是A已经被instantiate(实例化)之后,在populateBean(填充A中的属性)时,对B进行初始化。

对于问题2,instantiate(实例化)其实就是理解成new一个对象的过程,而new的时候肯定要执行构造方法,所以猜想对于应该是A在instantiate(实例化)时,进行B的初始化。

有了分析和猜想之后呢,围绕关键的属性,根据从上图的doGetBean方法开始到populateBean所有的代码,我整理了如下图:

对于问题1:单例的设值注入bean是如何解决循环依赖问题呢?如果A中注入了B,那么他们初始化的顺序是什么样子的?

假设循环注入是A-B-A:A依赖B(A中autowire了B),B又依赖A(B中又autowire了A):

本质就是三级缓存发挥作用,解决了循环。

对于当时问题2,instantiate(实例化)其实就是理解成new一个对象的过程,而new的时候肯定要执行构造方法,所以猜想对于应该是A在instantiate(实例化)时,进行B的初始化。

答案也很简单,因为A中构造器注入了B,那么A在关键的方法addSingletonFactory()之前就去初始化了B,导致三级缓存中根本没有A,所以会发生死循环,Spring发现之后就抛出异常了。至于Spring是如何发现异常的呢,本质上是根据Bean的状态给Bean进行mark,如果递归调用时发现bean当时正在创建中,那么久抛出循环依赖的异常即可。

总结:Spring在InstantiateBean时执行构造器方法,构造出实例,如果是单例的话,会将它放入一个singletonBeanFactory的缓存中,再进行populateBean方法,设置属性。通过一个singletonBeanFactory的缓存解决了循环依赖的问题。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Spring的beanFactory和factoryBean的区别

1. BeanFactory

  BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于管理Bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

  Spring为我们提供了许多易用的BeanFactory实现,XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。

FactoryBean

Spring 中为我们提供了两种类型的 bean,一种就是普通的 bean,我们通过 getBean(id) 方法获得是该 bean 的实际类型,另外还有一种 bean 是 FactoryBean,也就是工厂 bean,我们通过 getBean(id) 获得是该工厂所产生的 Bean 的实例,而不是该 FactoryBean 的实例。

FactoryBean 是一个 Bean,实现了 FactoryBean 接口的类有能力改变 bean,FactoryBean 希望你实现了它之后返回一些内容,Spring 会按照这些内容去注册 bean。
public interface FactoryBean<T>,提供如下方法:

  • T getObject()
  • Class<?> getObjectType()
  • boolean isSingleton()

通常情况下,bean 无须自己实现工厂模式,Spring 容器担任工厂 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。

    1.propagation_required:如果当前没有事务,就新建一个事务;如果已经存在一个事务,就加入到这个事务中。这是最常见的选择。

    2.propagation_requires_new:新建事务。如果当前存在事务,就把当前事务挂起。

    3.propagation_supports:支持当前事务。如果当前没有事务,就以非事务方式执行。

    4.propagation_not_supported:以非事务方式执行操作。如果当前存在事务,就把当前事务挂起。

    5.propagation_mandatory :使用当前事务。如果当前没有事务,就抛出异常。

    6.propagation_never:以非事务方式执行。如果当前存在事务,就抛出异常。

    7.propagation_nested:如果当前存在事务,就在事务内执行;如果当前没有事务,就执行与propagation_required类似的操作。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值