Spring中关于Bean需要了解的几点

目录

BeanFactory 和 ApplicationContext

SpringBean的生命周期

 Spring 中的 Bean 是线程安全的吗 ?

Bean循环依赖


         我们把由Spring创建的对象称为一个Bean , 关于Spring中 Bean存在很多的知识面, 例如生命周期, 循环依赖 , 接着我们来一一论述

BeanFactory 和 ApplicationContext

先来说BeanFactory , 顾名思义, 从名字上能看出, bean工厂, 是偏底层的一些东西

     在 spring 容器中,BeanFactory 接口是 IOC 容器要实现的最基础的接口,定义了管理bean 的最基本的方法,例如获取实例、基本的判断等

      这个接口中定义了一些基础的方法 , 例如 getBean()等, 当然作为底层接口, 也有很多子接口来进一步扩展bean的功能, 接着来看ApplicationContext

     ApplicationContext也间接继承了BeanFactory,如果说BeanFactory是Sping的心脏,那么ApplicationContext 就是完整的身躯了。它们都可以当做 Spring的容器,Spring 容器是生成 Bean 实例的工厂,并管理容器中的 Bean。

接着来看两者的区别

       首先BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身,是 Spring 中比较原始的Factory,它不支持 AOP、Web 等 Spring 插件, 而 ApplicationContext 不仅包含了 BeanFactory 的所有功能,还支持 Spring的各种插件,还以一种面向框架的方式工作以及对上下文进行分层和实现继承。

         意思就是说BeanFactory比较底层, 没有许多额外的功能等, 而ApplicationContext则支持各种额外功能, 并且包含BeanFactory所有功能(因为它两是间接继承关系)

 BeanFactory:需要等到获取某个 bean 的时候才会创建该 bean,即延迟初始化            ApplicationContext:在启动 Spring 容器时就会创建所有的 bean(Web 应用中推荐)

        BeanFactory等到需要的时候才会创建, 而ApplicationContext在Spring容器启动时就会创建所有的bean

SpringBean的生命周期

宏观上讲 , bean生命周期有5个阶段

       1. 实例化 Instantiation  2. 属性赋值 Populate  3. 初始化 Initialization 4. 将 bean 对象放入到容器中,使用  5. 销毁 Destruction

实例化

      就是创建一个原始的对象, 通过反射机制实现

属性赋值

      为所创建的对象中属性赋值

初始化

      这里的初始化主要有两点 :

      1. 如果类实现了某些接口并重写了接口中的某些方法 , 就去执行这些方法, 初始化我们的对象 , 对类进行了功能提升

      2. 如果此类是一个被增强的类(AOP), 那么就是在此处为bean添加功能

使用

      此时bean已被加入到spring容器中, 可以使用

销毁

      如果 Bean 实现 DisposableBean 执行 destroy , 如果配置了自己的销毁方法<bean destroy-method="customerDestroy"> , 指定销毁方法 customerDestroy

       以上就是bean生命周期的整个过程, 中间有很多过程都是初始化时是否执行某些方法, 如果没有实现这些接口, 那么这些过程也可以省略, 下图为上面过程的解释

 Spring 中的 Bean 是线程安全的吗 ?

       Spring 容器中的 Bean 是否线程安全,容器本身并没有提供 Bean 的线程安全策略,因此可以说Spring 容器中的 Bean 本身不具备线程安全的特性,但是具体还是要结合具体 scope(作用域) 的 Bean 情况。

       要谈论线程安全问题的话 , 可以分为单例 bean和原型 bean来探讨

       原型Bean : 每次都创建一个新对象 , 线程之间并不存在共享的bean , 自然不存在线程安全问题
       单例Bean : 多个线程共享一个Bean , 是存在线程安全问题的

      bean 又可以分为有状态和无状态

     有状态就是bean中包含可以操作的变量数据等, 而无状态则不包含这些

     如果单例bean 是一个无状态bean(没有向外界提供数据操作) , 毋庸置疑, 此时它就是线程安全的 , 但如果它是一个有状态的bean , 那么就存在线程安全问题 ,需要开发人员自己保证线程安全

Bean循环依赖

        Bean的循环依赖问题就是 两个对象相互依赖, 导致两个对象都无法创建

 试想我们不使用spring , 在javaSE中这种情况会出现吗 ?   答案当然是不会
 因为在创建A 时, 发现有B ,会赋null ,B同理 , 所以这种情况只在spring中出现(spring是自动注入的)
       spring中的bean和我们普通的对象不同 , 它需要经过一系列的生命周期, 所以如果出现循环依赖问题, 两者此时都无法创建, 那么如何来解决这一问题呢? 

为解决此问题, spring提供了三级缓存

      singletonObjects 一级缓存,用于保存实例化、注入、初始化完成的 bean 实例                   earlySingletonObjects 二级缓存,用于保存实例化完成的 bean 实例
     singletonFactories 三级缓存,用于保存 bean 创建工厂,以便于后面扩展有机会创建代理对象。

那么这三个缓存是怎样来解决此问题的 , 接着我们来论述

       假如现在有两个bean,A和B相互依赖 , 首先创建A , 先创建A的原始对象(实例化), 发现A中包含B, 此时这个半成品A会最终存入到二级缓存中, 接着去创建 B , 发现B 中包含A , 将二级缓存中的A取出注入到B中, 此时B被创建完成, 存入一级缓存中 , 这时回到创建A的过程, 将一级缓存中的B取出赋给A 中, 至此循环依赖问题解决

那么这时可能有人会说了, 不是有3级缓存吗? 那第三层缓存呢? 接着我们来说

      其实在解决依赖之前, 第三级缓存就已经使用过了(感兴趣可以去看源码具体实现), 但它最主要的功能是解决功能增强问题(AOP) , 就是说我们发现A中B存在要增强的功能 , 那么此时二级缓存就无法顾及这么多了, 三级缓存做到了缓存工厂, 可以对bean进行加工 . 所以可以得出结论 : 二级缓存主要解决依赖问题, 三级缓存解决功能增强问题(AOP)

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值