Spring系列之 Bean的生命周期

Spring系列之 Bean的生命周期

我叫Spring,今天为大家介绍5.x版本的我,体内最核心的运行原理之一——IOC(控制反转)中Bean的生命周期。后续将基于此一步一步拆解我的身体,为大家做更多的原理性介绍,帮大家在面试和走向架构岗位做一点点贡献。

首先程序员大哥们在我身体上编写的各种Bean, 是我的体内最为核心的东西。

Bean在我体内,会经历三个大的阶段:生产、使用、销毁。其中,以生产阶段最为复杂。在程序员命令我启动的那一刻开始,我体内的生产线就开始准备生产一个个的Bean
启动过程很复杂,下一个视频会为大家详细介绍。

在我启动之初,为了精准地了解程序员对于Bean的要求,我使用XML配置、注解扫描等各种方式,将程序员在我体内定义的Bean类一个个找到,即BeanDefinitionMap

有了这些“Bean定义”集合之后,我就可以遍历这个集合,然后通过我体内的createBean方法,为程序员创建一个个Bean对象。

创建Bean大体分为“构造对象、填充属性、初始化实例、注册销毁”四个步骤:

首先,构造对象。我用反射机制从“Bean定义”中的BeanClass拿到这个类的构造方法。当然,我在拿取构造方法时,是有一些规则的。

如果这个Bean只有一个构造方法,那毫无疑问我只能拿它,无论这个构造方法有没有入参。当Bean中有多个构造方法时,我会先拿带有@Autowired注解的构造方法。当然,如果多个构造方法都加了@Autowired注解,那么我只能报错。如果构造方法都没有@Autowired注解,我就会优先拿无入参的方法。如果多个构造方法都是有入参的,我也无法判断具体拿哪一个,所以又要报错。我非常不建议程序员在任何Bean中添加多个构造方法,这样可读性低,理解和维护会很困难。
在我们选择了确定的构造方法之后,就要准备这个构造方法需要的参数了。我会在我的单例池中,根据参数的Class类进行查找。如果这个类在我的体内有多个实例,则会根据参数名再进行匹配。如果没有找到,我就会认为构造信息导致不完整,而直接报错。在参数准备好之后,通过反射就可以进行Bean的构造,也就是我们常说的实例化。当然,如果选择的是无参构造方法,则无需参数直接构造。

其次,填充属性。在Bean对象构造成功后,接下来就进行属性填充。通常就是@Autowired注解的这些变量,我会通过“三级缓存”机制进行填充,也就是我们所谓的依赖注入。三级缓存后续会详细介绍。

然后初始化实例,在属性填充后,紧接着就要通过initializeBean方法,对这个实例进行初始化了。初始化的第一步是初始化容器相关信息,通过invokeAwareMethods方法,为实现了各种Aware接口的Bean设置诸如beanNamebeanFactory等容器信息。这里要注意的是,我体内的Aware接口代表“信息感知”接口,一旦实现了这些接口,就可以在Bean实例中感知并获取到对应的信息,真的非常方便。这个初始化方法,是程序员通过实现InitializingBean接口而实现的afterPropertiesSet方法,方法名很直接,表示“Bean填充属性后”执行。在afterPropertiesSet执行后,在执行初始化方法之前和之后,我通过applyBeanPostProcessorsBeforeInitializationapplyBeanPostProcessorsAfterInitialization,处理各种Bean的后置处理器。这些处理器包括我自身提供的负责AOP处理的AspectJInitDestroyAnnotationBeanPostProcessor等系统级处理器,以及程序员通过实现BeanPostProcessor接口的自定义处理器。当然,这些处理器有很多,可以通过实现PriorityOrdered接口来指定顺序,进行逐一处理。

最后,注册销毁。其实上面步骤完成时,Bean实例就已经可用了。为了让Bean优雅地销毁,我通过registerDisposableBean方法,这样在销毁时就可以执行destroy方法了。通过以上四小步,我们就将Bean创建好了。这样,“产生Bean”就全部完成啦。
接下来,最后,当我执行close关闭睡觉的时候,和“产生Bean”类似,在销毁之前要先执行“销毁前处理器”。这里就会执行Bean中的@PreDestroy注解的方法,销毁时会执行刚提到的destroy方法。在destroy执行之后,执行客自定义的代码。Bean的生产、使用到销毁这一套完整的生命周期就介绍完了。
如果你喜欢这期视频的话,请一定记得长按点赞按钮。