Spring系列之 Bean的生命周期
Spring系列之 Bean的生命周期
ShioSpring系列之 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
设置诸如beanName
、beanFactory
等容器信息。这里要注意的是,我体内的Aware
接口代表“信息感知”接口,一旦实现了这些接口,就可以在Bean
实例中感知并获取到对应的信息,真的非常方便。这个初始化方法,是程序员通过实现InitializingBean
接口而实现的afterPropertiesSet
方法,方法名很直接,表示“Bean
填充属性后”执行。在afterPropertiesSet
执行后,在执行初始化方法之前和之后,我通过applyBeanPostProcessorsBeforeInitialization
和applyBeanPostProcessorsAfterInitialization
,处理各种Bean
的后置处理器。这些处理器包括我自身提供的负责AOP
处理的AspectJ
、InitDestroyAnnotationBeanPostProcessor
等系统级处理器,以及程序员通过实现BeanPostProcessor
接口的自定义处理器。当然,这些处理器有很多,可以通过实现PriorityOrdered
接口来指定顺序,进行逐一处理。
最后,注册销毁。其实上面步骤完成时,Bean
实例就已经可用了。为了让Bean
优雅地销毁,我通过registerDisposableBean
方法,这样在销毁时就可以执行destroy
方法了。通过以上四小步,我们就将Bean
创建好了。这样,“产生Bean
”就全部完成啦。
接下来,最后,当我执行close
关闭睡觉的时候,和“产生Bean
”类似,在销毁之前要先执行“销毁前处理器”。这里就会执行Bean
中的@PreDestroy
注解的方法,销毁时会执行刚提到的destroy
方法。在destroy
执行之后,执行客自定义的代码。Bean
的生产、使用到销毁这一套完整的生命周期就介绍完了。
如果你喜欢这期视频的话,请一定记得长按点赞按钮。