在上一篇文章中已经对Spring扫描流程进行了解析,这一篇spring之bean的生命周期就接着上一篇继续讲。
https://blog.csdn.net/u014518603/article/details/135333272
bean的生命周期流程
- 生成beanDefinition:通过上一篇扫描得到
- 合并beanDefinition
- 加载类
- 实例化前:若在此返回一个bean,则直接跳到初始化后aop步骤
- 实例化
- BeanPostProcessor后置处理器
- 实例化后
- 属性填充:自动注入autowireMode
- 属性填充:@Autowired @Resource
- 执行aware回调
- 初始化前 :包括@PostConstruct
- 初始化: InitializingBean.afterPropertiesSet() , init-method
- 初始化后
合并父子BeanDefinition
spring启动扫描完成后,得到了beanDefinitionMap,接着调用AbstractApplicationContext.refresh()
中的finishBeanFactoryInitialization()
方法,最终调用的是beanFactory.preInstantiateSingletons();
实例化所有非懒加载的单例bean。此处的beanFactory具体是DefaultListableBeanFactory。
进入beanFactory.preInstantiateSingletons();
方法后,下一步调用getMergedLocalBeanDefinition()
方法合并父子beanDefinition,得到RootBeanDefinition。
创建factoryBean
如果当前beanDefinition是factoryBean,则将&beanName
传参给getBean()
方法获取bean。
getBean()
会调用doGetBean()
方法。先截取&,然后从单例池获取bean。获取到bean后再调用方法getObjectFromBeanInstance()
判断是否是factoryBean
如果getObjectFromBeanInstance()
判断当前bean是factoryBean,
则调用getCachedObjectForFactoryBean()
方法先从factoryBeanObjectCache
缓存中获取。
缓存中不存在则调用getObjectFromFactoryBean()
,最终是调用factoryBean的getObject()
方法生成bean,并放入缓存factoryBeanObjectCache。
创建普通单例bean
如果当前beanDefinition不是factoryBean,则进入DefaultListableBeanFactory.getBean()
方法开始创建bean,调用doGetBean(),获取父beanFactory,从当前beanFactory获取不到beanDefinition,则从父beanFactory获取。
接下来开始合并父子beanDefinition,调用getMergedLocalBeanDefinition()
生成的新RootBeanDefinition,checkMergedBeanDefinition()
检查RootBeanDefinition是抽象的,则抛异常,因为抽象beanDefinition不能生成bean。
然后获取beanName对应的dependsOn依赖类,存入数组dependsOn
遍历数组dependsOn,如果出现两个类互相依赖,则抛异常。
将@DependsOn(“xxx”)中的xxx存到dependentBeanMap中,表示某个bean,被哪些bean依赖了。然后通过getBean()获取依赖的bean。
判断作用域
- 当前beanDefinition的作用域是单例的,先从单例池获取,找不到再调用createBean();
- 当前beanDefinition的作用域是原型的,则直接调用createBean()创建新的实例。
进入createBean()主流程
加载class对象
首先加载class对象,resolveBeanClass()
根据beanName从beanDefinition的beanClass属性获取到Object类型的字符串"com.xx.Student"。然后克隆出一个RootBeanDefinition,将获取到的class对象设置到beanClass属性中。
实例化前
resolveBeforeInstantiation()
,如果在这一步就返回一个bean,那么后面就直接跳到初始化后的步骤进行aop操作了。
执行接口InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
方法
@Component
public class WjBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("student".equals(beanName)) {
System.out.println("实例化前");
// 如果在这里return一个实例化的对象,则后面的步骤不会再执行,直接直接初始化后的操作
}
return null;
}
}
实例化
doCreateBean()
会调用createBeanInstance()
创建bean对象,通过推断构造方法,或者通过自动注入模型的autowireMode = byConstructor
实例化后
执行接口InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
方法
属性填充
通过自动注入模型autowireMode
填充属性
populateBean()
通过beanDefinition的autowireMode字段属性进行自动注入。通过xml配置aotuwire=“byName”、"byType"来设置自动注入的模式。
注:这种方式现在已经不推荐使用了,因为它的控制粒度不够细,类中的所有set方法都会被当做注入点。而@Autowired可以加在属性、方法、构造方法上,可以由开发人员控制在哪里进行注入。
通过byName、byType两种方式注入需要在类中提供set方法。
byName:通过解析setXXX()
拿到XXX作为beanName去容器中获取bean,找不到则报错,XXX必须与beanName一致。
byType:通过setXXX( YYY yyy);
拿到属性类型,并根据类型去容器中找bean,找不到则报错。
通过解析注解@Autowired、@Resource
填充属性
获取所有实现了接口InstantiationAwareBeanPostProcessor.postProcessProperties()
方法的beanPostProcessor,遍历它们。其中两个重要类是AutowiredAnnotationBeanPostProcessor
用于解析@Autowired注解,
CommonAnnotationBeanPostProcessor
用于解析@Resource注解。
找到注入点集合,封装到对象InjectionMetadata中,然后遍历注入点集合,通过反射给bean注入属性。
初始化
initializeBean()
aware回调
invokeAwareMethods()
初始化前
applyBeanPostProcessorsBeforeInitialization()
执行所有实现了接口BeanPostProcessor.postProcessBeforeInitialization()
方法。这一步包含了@PostConstruct方法的执行
初始化
invokeInitMethods()
执行接口InitializingBean.afterPropertiesSet()
方法
invokeInitMethods()
执行从RootBeanDefinition
的属性initMethod
获取到的初始化方法,可以通过beanDefinition指定initMethod,或者通过xml给bean配置一个属性init-method来指定初始化的方法。
初始化后
applyBeanPostProcessorsAfterInitialization()
执行所有实现了接口BeanPostProcessor.postProcessAfterInitialization()
方法
处理循环依赖
定义bean的销毁逻辑
最后,
DefaultListableBeanFactory.preInstantiateSingletons()
方法在创建完成所有的非懒加载的单例bean后,会再次遍历单例池中的bean,判断是否实现了接口SmartInitializingSingleton,然后执行它的方法afterSingletonsInstantiated()