Spring中Bean的生命周期

概述:Spring框架核心模块中的IOC容器为我们提供了创建Bean和管理Bean以及管理Bean的生命周期的功能,IOC思想的引入后,不在通过new手动创建对象,这一切都交给了Spring框架完成,掌握Spring中Bean的生命周期有助于我们对IOC思想的理解,下面详细描述Bean的声明周期。

Bean的生命周期:实例化——>初始化——>操作使用——>销毁

一、实例化:

  • 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象;
  • 将BeanDefinition存储在一个名为beanDefinitionMap的Map中;
  • ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象;

Spring中Bean的生命周期_第1张图片

Spring的2种后处理器:

1、BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例 化之前执行;

2、BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects 之前执行。

二、初始化:

Bean创建之后还仅仅是个"半成品",还需要对Bean实例的属性进行填充、执 行一些Aware 接口方法、执行BeanPostProcessor方法、执行InitializingBean接口的初始化方 法、执行自定义初始化init方法等。

初始化操作需要:创建好的Bean实例对象,被存储到一个名为singletonObjects的Map中; 当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回

Bean的初始化步骤:

  • Bean实例的属性填充(set方法)
  • Aware接口属性注入【提供扩展】
  • BeanPostProcessor的before()方法回调(----------Bean后处理器的前置方法)
  • InitializingBean接口的初始化方法回调
  • 自定义初始化方法init回调
  • BeanPostProcessor的after()方法回调(------------Bean后处理器的后置方法)

常用Aware接口

Aware接口 回调方法 作用
ServletContextAware setServletContext(ServletContext context) 注入ServletContext对象【Web环境下生效】
BeanFactoryAware    setBeanFactory(BeanFacotry factory) 注入beanFactory对象
BeanNameAware setBeanName(String beanName) 注入beanName
ApplicationContextAware        setApplicationContext(ApplicationContext context) 注入applicationContext对象

在初始化第一阶段对属性填充时,对于双向引用属性可能会设计循环依赖问题:

Spring中的循环依赖:类与类直接的依赖关系形成了闭合,如下图所示:

Spring中Bean的生命周期_第2张图片

在注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没 有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;

双向引用可以看作是2个方向的单向引用

上图所示的循环依赖问题:Service实例化对象,接着初始化,需要Dao,容器中没有Dao对象,先去创建Dao,实例化Dao对象,初始化Dao,需要Service,容器中此时也没有Service对象。

解决方案:Spring提供三级缓存存储 完整Bean实例 和 半成品Bean实例 ,用于解决循环引用问题

//1、最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存" MapsingletonObjects = new ConcurrentHashMap(256);

//2、早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存" Map earlySingletonObjects = new ConcurrentHashMap(16);

//3、单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三级缓存" Map singletonFactories = new HashMap(16);

引入三级缓存后:

  • UserService 实例化对象,但尚未初始化,将UserService存储到三级缓存;
  • UserService 属性注入,需要UserDao,从缓存中获取,没有UserDao;
  • UserDao实例化对象,但尚未初始化,将UserDao存储到到三级缓存;
  • UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService从三级缓存移 入二级缓存;
  • UserDao执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存;
  • UserService 注入UserDao;
  • UserService执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓 存。

三、操作使用:

以上步骤就是Spring框架为我们创建对象的基本过程,此时的Bean可以正常通过我们操作使用就是调用ApplicationContext应用上下文对象getBean()获取“已成型”的Bean对象直接操作即可

四、销毁:

  • DisposableBean接口的初始化方法回调:当Bean不再需要时,会警告清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destory()执行销毁
  • 自定义初始化方法destory回调:如果这个Bean的Spring配置中配置了destory-method属性,会自动调用其配置的自定义销毁方法。

最后总结归纳为2道常见面试题:

1、Spring框架中Bean的声明周期?

2、Spring框架如何解决循环依赖?

你可能感兴趣的:(spring)