【Spring总结】Spring Bean

1、面试题:Spring Bean的生命周期

image-20220326142539603

即bean从创建到销毁spring做了哪些事情?

阶段5、7比较重要。

spring里面的bean都是懒惰式的初始化,当你第一次去获取它的时候,他才会去创建bean的实例,进行依赖注入、初始化。

阶段1:处理名称,检查缓存

要点

  • 掌握别名处理
  • 了解FactoryBean的名字规范
  • 掌握三级缓存的概念

1、spring当中支持别名,一个bean可以有多个名称。

2、FactoryBean式spring当中专门用来生产其他对象的工厂bean。如果想要获取工厂本身的名称,而不是工厂里里面的bean,需要在名称前面加一个&

总结

  • 先把别名解析为实际名称,再进行后续处理
  • 若要 FactoryBean本身,需要使用&名称获取
  • singletonObjects是一-级缓存, 放单例成品对象
  • singletonFactories是三级缓存,放单例工厂
  • earlySingletonObjects是二级缓存,放单例工厂的产品,可称为提前单例对象

首先去一级缓存里面查找看有没有创建好的单例对象。如果有,就不用创建了。

二级缓存和三级缓存主要用来解决循环依赖的问题。

三级缓存就可以解决循环依赖问题。那为什么还要二级缓存?

二级缓存是用来解决,需要在代理的情况下还有循环依赖的问题。

阶段2:处理父子容器

要点

  • 了解有父容器时的查找规则

当缓存中没有实例对象,也不会立马去创建。如果容器中还配置了父容器,缓存里没有找到,会去父容器里查找这个对象。父容器如果有,就直接使用父容器里面的bean。如果这样还有没,就会走创建的流程。

总结

  • 父子容器的 bean名称可以重复
  • 优先找子容器的bean,找到了直接返回,找不到继续到父容器找

阶段3: dependsOn

什么是dependsOn?

大部分bena之间都是由依赖关系的,有依赖关系的bean的创建次序是可以得到保障的。例如A依赖于B,那就先创建B,在创建A。

但是有的bean之间没有显式的依赖关系,但是又想控制他们的创建次序,使用A dependsOn B,那就是B先创建后A再创建.

阶段4:按Scope创建bean

要点

  • 理解三种scope

singleton,prototype,request,session,

1.单例Bean从refresh被创建,到close被销毁.

image-20220326144900551

2,prototype多例Bean从首次getBean被创建,到调用BeanFactory的destroyBean被销毁.

image-20220326145204985

容器启动refresh和关闭的时候,并不会导致多例bean的创建和销毁.那什么时候多例bean被创建呢?

当调用getBean使用它的时候

image-20220326145445722

创建时间:单例bean是在容器启动refresh式被创建,多例bean是在调用使用她的时候,使用getBean()方法去创建.

销毁时间:单例bean是在容器关闭时,多例bean需要我们自己去调用它的销毁方法.

3,request bean从首次getBean被创建,到request结束前被销毁

创建好了之后放在request作用域,在request作用域销毁之前,将于该域相关的bean销毁.

image-20220326145959681

其实他们三个bean的起点都是从getBean()开始,只不过终点不一样,单例是在容器结束前.基于某一个request Scope的,他是在特定的请求域结束前.至于propotype是自己控制什么时候把它销毁.

总结

  • scope 理解为从xXX范围内找这个bean更加贴切
  • singleton scope表示从单例池范围内获取bean,如果没有,则创建并放入单例池.
  • prototype scope表示从不缓存bean,每次都创建新的
  • request scope表示从request对象范围内获取bean,如果没有,则创建并放入request …

阶段5:创建bean

image-20220326153411767

单例对象创建好之后被放入到单例池中,request被放入对应的request域中,propotype哪里都不放,由自己去管理它.

创建阶段 ,依赖注入阶段, 初始化阶段, 注册和销毁bean阶段

每个小阶段都会有对应的beanPostProcessor,对每个阶段的功能进行扩展.比例解析成员变量或者方法上的注解,创建代理对象等.

阶段5-1:创建bean实例

1.优先选择带@Autowired注解的构造器创建实例.

2.若有唯一的带参构造,也会入选

image-20220326154330414

但是如果构造方法是私有的,使用暴力反射,将setS…设为true进行构造.

阶段5-2:依赖注入

bean的实例对象刚创建时,里面空空如也,还不能正常工作.

  1. 我们的后置处理器只是找到那个成员变量或者成员方法加了@Autowired,@Value注解,找到之后交给InjectionMetadata进行依赖注入.

image-20220326155226080

针对同一个成员采用多种依赖注入的方式,那哪种方式会成功?

按照名字去进行以来注入的时候,是先去除方法的set之后再将方法名首字母小写,就是bean的名字.

即在下面例子中,如果按照名字注入的方式应该是bean3被注入进去.

image-20220326155648187

image-20220326155854231

image-20220326160107176

精确指定注入的bean方式 > 根据名字注入 > AutoWired注解注入

阶段5-3:初始化

首先会处理一些Aware接口,比如一些BeanNameAware接口,BeanFactoryAware接口.

之后调用初始化方法(有三种不同的初始化方式)

@PostConstruct是通过后置处理器CommonAn…调用的.

在beanDedintion里面规定那个方式是初始化方法,可以使用xml配置或者注解@Bean

image-20220326160825384

初始化做的三件事:调用Aware接口,调用初始化方法,创建AOP代理

其中解析注解和创建动态代理都是通过后置处理器帮助实现.

初始化顺序:先是Aware接口 > 注解@PostConstruct > InitalizingBean > initMethod

阶段5-4:注册可销毁bean

要点

  • 判断并登记可销毁bean

总结

  • 判断依据

    • 如果实现了DisposableBean或AutoCloseable接口,则为可销毁bean
    • 如果自定义了destroyMethod,则为可销毁bean
    • 如果采用@Bean没有指定destroyMethod,则采用自动推断方式获取销毁方法名( close, shutdown)
    • 如果有@PreDestroy标注的方法
  • 存储位置

    • singleton scope的可销毁bean会存储于beanFactory的成员当中
    • 自定义scope的可销毁bean会存储于对应的域对象当中
    • prototype scope不会存储,需要自己找到此对象销毁
  • 存 储时都会封装为DisposableBeanAdapter类型对销毁方法的调用进行适配

阶段6:类型转换

要点

  • 如果getBean的requiredType参数与实际得到的对象类型不同,会尝试进行类型转换

这个时候Bean已经被创建返回.

阶段7:销毁bean

要点

  • singleton bean的销毁时机
  • 自定义scope bean的销毁时机
  • prototype bean的销毁时机
  • 同一bean中不同形式销毁方法的调用次序

总结

  • singleton bean的销毁在ApplicationContext.close 时,此时会找到所有DisposableBean的名字,逐-销毁
  • 自定义scope bean的销毁在作用域对象生命周期结束时(例如request)
  • prototype bean的销毁可以通过自己手动调用AutowireCapableBeanFactory.destroyBean方法执行销毁
  • 同一bean中不同形式销毁方法的调用次序
    • 优先后处理器销毁,即@PreDestroy
    • 其次DisposableBean接口销毁
    • 最后destroyMethod销毁( 包括自定义名称,推断名称,AutoCloseable 接口多选一)

总结

image-20220326162621520

  • 阶段1:处理名称,检查缓存(处理别名,看看缓存里有没有,有就直接返回,没有再执行后续流程.)

  • 阶段2:检查父工厂(当前bean名字在缓存里没有找到,会去找对应的父工厂)

  • 阶段3:检查DependsOn(检查依赖关系,先创建DependsOn后面的bean)

  • 阶段4:按Scope创建bean
    ①创建singleton
    ②创建 prototype
    ③创建其它 scope

  • 阶段5:创建bean
    ①创建 bean实例- @Autowired,唯一带参构造, 默认构造(优先采用注解@Autowired)

    ②依赖注入 - @Autowired @Value(AutowiredBeanPostProcessor后置处理器处理这两个注解), @Resource(CommonAnnotationBeanPostProcessor后置处理器处理这个注解), ByName ByType(根据名字匹配还是根据类型匹配),精确指定

    (优先级: 精确指定 > 根据名字或者类型匹配 > 注解)

    ③初始化- Aware接口处理,@PostConstruct, InitializingBean, initMethod

    (优先级:从前到后依次降低)

    ④登记可销毁 bean

  • 阶段6:类型转换

这两个注解), @Resource(CommonAnnotationBeanPostProcessor后置处理器处理这个注解), ByName ByType(根据名字匹配还是根据类型匹配),精确指定

(优先级: 精确指定 > 根据名字或者类型匹配 > 注解)

③初始化- Aware接口处理,@PostConstruct, InitializingBean, initMethod

(优先级:从前到后依次降低)

④登记可销毁 bean

  • 阶段6:类型转换

  • 阶段7:销毁bean

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值