【JAVA面试基础】Spring IOC(自动注入,BeanFactory,自动配置,Spring生命周期,三层缓存)思想串讲

1.IOC思想概述

      所谓的IOC(inversion of control),就是控制反转的意思。

      原来这个对象的控制权在我们的代码中,我们自己new的对象,在Spring中,应用程序不再控制对象的创建,而是被动地接受由容器注入的对象。

       控制权被转移到Spring容器中,容器负责创建和管理对象,并在需要的时候将它们注入到应用程序中。

2.继承关系

这边主要介绍BeanFactoryApplicationContext

  • ApplicationContext是BeanFactory的子类,并且与beanFactory是组合的关系。并且每次getBean()底层都是依赖BeanFactory来进行依赖查找
  • BeanFactory是IOC的底层,提供了最基本的方法。而ApplicationContext是beanFactory的派生,提供了许多beanFactory所不能完成的功能,同时也拥有BeanFactory的所有功能,是对BeanFactory的扩展
  • 在实际使用中也更多的是使用ApplicationContext来获取对象,判断是否单例等

3.SpringBoot对Bean的管理

Bean的Spring容器加载

Bean的来源一共就两种方式:

  • 第三方bean:SpringBoot的自动配置
  • 本地bean:使用@Conponent
 自动配置

由于使用了EnableAutoConfiguration注解,该注解Import的EnableAutoConfigurationImportSelector会去扫描classpath下的所有spring.factories文件,自动的给你生成一些Bean,并加载到Spring的Context中。

@Conponent

由自己添加注解,将该类交由Spring容器管理 

Spring Bean生命周期

       整个生命周期可以大致分为3个大的阶段,分别是:创建、使用、销毁。还可以进一步分为5个小的阶段:实例化、初始化、注册Destruction回调、Bean的正常使用以及Bean的销毁。

具体到代码方面,可以参考以下这个更加详细的过程介绍,我把具体实现的代码位置列出来了。

实例化Bean:

  • Spring容器首先创建Bean实例。
  • 在AbstractAutowireCapableBeanFactory类中的createBeanInstance方法中实现

设置属性值:

  • Spring容器注入必要的属性到Bean中。
  • 在AbstractAutowireCapableBeanFactory的populateBean方法中处理

检查Aware:

  • 如果Bean实现了BeanNameAware、BeanClassLoaderAware等这些Aware接口,Spring容器会调用它们。
  • 在AbstractAutowireCapableBeanFactory的initializeBean方法中调用

调用BeanPostProcessor的前置处理方法:

  • 在Bean初始化之前,允许自定义的BeanPostProcessor对Bean实例进行处理,如修改Bean的状态。BeanPostProcessor的postProcessBeforeInitialization方法会在此时被调用。
  • 由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法执行。

调用InitializingBean的afterPropertiesSet方法:

  • 提供一个机会,在所有Bean属性设置完成后进行初始化操作。如果Bean实现了InitializingBean接口,afterPropertiesSet方法会被调用。
  • 在AbstractAutowireCapableBeanFactory的invokeInitMethods方法中调用。

调用自定义init-method方法:

  • 提供一种配置方式,在XML配置中指定Bean的初始化方法。如果Bean在配置文件中定义了初始化方法,那么该方法会被调用。
  • 在AbstractAutowireCapableBeanFactory的invokeInitMethods方法中调用。

调用BeanPostProcessor的后置处理方法:

  • 在Bean初始化之后,再次允许BeanPostProcessor对Bean进行处理。BeanPostProcessor的postProcessAfterInitialization方法会在此时被调用。
  • 由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization方法执行

注册Destruction回调:

  • 如果Bean实现了DisposableBean接口或在Bean定义中指定了自定义的销毁方法,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭时能够正确地清理资源。在AbstractAutowireCapableBeanFactory类中的registerDisposableBeanIfNecessary方法中实现

Bean准备就绪:

  • 此时,Bean已完全初始化,可以开始处理应用程序的请求了。

调用DisposableBean的destroy方法:

  • 当容器关闭时,如果Bean实现了DisposableBean接口,destroy方法会被调用。
  • 在DisposableBeanAdapter的destroy方法中实现

调用自定义的destory-method:

  • 如果Bean在配置文件中定义了销毁方法,那么该方法会被调用。
  • 在DisposableBeanAdapter的destroy方法中实现
初始化阶段对Bean处理

这里主要列举可以实现哪些功能

  • 缓存预热
  • Bean的优先加载
Bean的实例化时机 

对于Prototype:

  • 在第一次请求的时候才被实例化的

对于Singleton:

  • 一般在IoC容器启动的时候就被实例化,然后被缓存在内存中
  • 如果bean标签中有设置lazy-init=true,则会在第一次请求时才会被实例化,而不是在容器启动的时候就被实例化
  • 但是,当一个懒实例化的Bean依赖了一个非懒实例化的Bean,那么IOC容器在启动的时候也会实例化这个Bean,因为它必须满足单例的依赖性

在默认情况下:

spring容器会在启动时就创建并初始化所有的单例Bean(@Conponent注解的默认作用域是单例) 

Bean的自动注入
@Autowired(Spring自带)

 Autowired在获取bean的时候,先是byType的方式,再是byName的方式。意思就是先在Spring容器中找以Bean为类型的Bean实例,如果找不到或者找到多个bean,则会通过fieldName来找.

@Resource(JDK自带)

Resource在获取bean的时候,和Autowired恰好相反,先是byName方式,然后再是byType方式。当然,我们也可以通过注解中的参数显示指定通过哪种方式。

作用域不同
  • Autowired可以作用在构造器,字段,setter方法上
  • Resource 只可以使用在field,setter方法上

4.Bean自动注入所存在的问题

这边只做简单介绍,不理解的部分欢迎留言。

循环依赖
  • 在Spring框架中,循环依赖是指两个或多个bean之间相互依赖,形成了一个循环引用的情况。如果不加以处理,这种情况会导致应用程序启动失败。
  • 在Spring中,解决循环依赖的方式就是引入了三级缓存。
三层缓存所存在的问题

Spring解决循环依赖是有一定限制的:

  • 首先就是要求互相依赖的Bean必须要是单例
  • 另外就是依赖注入的方式不能都是构造函数注入的方式
@Lazy 
  •  用来解决构造器注入这种方式下的循环依赖。
思考 
  • 为什么只支持单例
  • 为什么三层缓存不能解决构造器注入
  • 构造器注入和字段注入有啥区别

欢迎评论区留言交流!共同进步!

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值