Spring之Bean生命周期源码解析
Bean的生命周期Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建对象做准备,所以我们要先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。
Bean的生命周期是指:在SpringBean中,一个Bean是如何生成、如何烧毁的。
Bean的生命周期流程如下图所示:
https://p6.toutiaoimg.com/large/pgc-image/45f9ce89a004409eb3c3d35517459ac5
[*]注册BeanDefinition
[*]合并BeanDefinition
[*]加载类
[*]实例化前处理
[*]推断构造函数
[*]实例化
[*]BeanDefinition后置处理
[*]属性填充
[*]执行Aware
[*]初始化前置处理
[*]初始化
[*]初始化后置处理
[*]注册烧毁接口
1.注册BeanDefinition
BeanDefinition是什么
BeanDefinition中存在许多属性用来描述一个Bean的特点,好比:
[*]beanClassName,表示Bean范例名称
[*]scope,表示Bean作用域
[*]lazyInit,表示该Bean是否懒加载
[*]initMethodName,表示初始化方法名字
[*]destroyMethodName,表示烧毁方法名字
[*]constructorArgumentValues,表示构造器参数值
[*]还有许多...
为什么需要BeanDefinition
Spring IOC容器本质上是一个ConcurrentHashMap,key为Bean的Name,Value为Bean的实例对象。
https://p5.toutiaoimg.com/large/pgc-image/bc104eb8d9d84b9ab90f1b5205722ab8
大概你会说,我通过反射机制实例化一个目标对象,以Bean范例名称为key,目标对象为value,存入IOC容器中,不就可以了吗?Spring为什么要搞这么复杂?
我想,Spring之所以如许计划的目标,是可定制性及扩展性。Spring作为一个容器框架,通过IOC(控制反转)和DI(依赖注入)实现Bean之间依赖关系的管理以及Bean的生命周期管理。要实现Bean依赖关系的管理,必然要辨认出依赖关系,并把这些信息保存下来以供创建Bean实例时使用 ;要实现Bean的生命周期管理,必然要辨认出Bean有哪些生命周期扩展点以及每个扩展点的处理逻辑,并把这些信息保存下来以供创建Bean实例时使用。
这些信息可以看作是Bean的元数据信息,它们应该保存在哪儿呢?
说到这儿,你应该已经恍然大悟了,这些元数据信息就保存在BeanDefinition中,这些元数据信息将会用于指导Bean的创建及生命周期管理。
怎么注册BeanDefinition
在Spring中,我们经常会通过以下几种方式来界说Bean
[*]
[*]@Bean
[*]@Component(@Service,@Controller等)
这些,我们可以称之为声明式界说Bean。
我们还可以编程式界说Bean,即直接通过BeanDefinition,好比:
https://p26.toutiaoimg.com/large/pgc-image/81ca243fabc5470eb5cecc1ecd588587
我们还可以通过BeanDefinition设置Bean的其他属性,好比:
https://p5.toutiaoimg.com/large/pgc-image/9de7d01f0bab4f8089809b223be9c142
2.合并BeanDefinition
通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了,但是在Spring中支持父子BeanDefinition。
父子BeanDefinition实际用的比较少,使用是如许的,好比:
这么界说的环境下,child是单例Bean。
但是这么界说的环境下,child就是原型Bean了。
由于child的父BeanDefinition是parent,所以会继承parent上所界说的scope属性,当然,其他属性也会继承。而在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整child的BeanDefinition。
3.加载类
BeanDefinition合并之后,就可以先去创建Bean对象了,而创建Bean就必须先实例化对象,而实例化就必须先加载BeanDefinition中对应的class,在AbstractAutowireCapableBeanFactory类的createBean方法中,一开始就会调用:
Class resolvedClass = resolveBeanClass(mbd, beanName);这行代码就是去加载类,方法是这么实现的:
if (mbd.hasBeanClass()) { return mbd.getBeanClass();}if (System.getSecurityManager() != null) { return AccessController.doPrivileged((PrivilegedExceptionAction 转发了
页:
[1]