【bean的生命周期】--- 对象创建+初始化流程分析 --- 【重点@Autowired的作用时机】


1 简述

在spring环境下bean的生命周期大致可以分为下面三种情况:

(1)多实例,bean的创建、初始化在bean被使用的时候,bean的销毁由JVM的垃圾回收器进行处理。
(2)单实例懒加载的bean(注意:懒加载一般指的是单实例bean):创建、初始化在bean第一次被使用的时候,之后便和单实例bean一样了,销毁在IOC容器关闭的时候。
(3)单实例bean:bean的创建、初始化在项目启动时,销毁在IOC容器关闭时。

本文主要来剖析单实例bean的创建+初始化过程。


2 源码解析之主干分析

感觉自己写博客也有一段时间了,现在回过头来看自己原来关于源码解读的文章,很多我自己都看不下去,感觉就是干巴巴的一行行的解读源码,但是回过头却很难一下就抓住整个代码的主干,所以这次我打算换种方式来写这篇文章。

跟踪源码发现,在spring中单实例bean真正创建+初始化的骨架被封装在了AbstractAutowireCapableBeanFactory类的doCreateBean方法里。在该方法里主要包含如下三个方法:
在这里插入图片描述


3 源码解析之详细解读

下面将对doCreateBean中的三个主要方法做进一步地解析。


3.1 bean的创建 — Instantiate the bean

// Instantiate the bean.
createBeanInstance(beanName, mbd, args); // 源码538行

对于使用@Component注入IOC容器的对象来说就是new当前对象


对于使用@Bean注入的对象来说会走@Bean注解指定的方法来new当前对象—>当然可以在这里向当前对象里set一些属性,如:

@Bean(name = "cat")
public Cat buildCat() {
    Cat cat = new Cat();
    cat.setName("花花"); //为bean设置一些属性
    return cat;
}

注意: 但是通过@Autowired注入的属性不会在这一步进行注入。


3.2 bean的初始化 — Initialize the bean instance

包括如下两步:

// Initialize the bean instance.
populateBean(beanName, mbd, instanceWrapper); // 源码575行
exposedObject = initializeBean(beanName, exposedObject, mbd); // 源码576行

3.2.1 populateBean(beanName, mbd, instanceWrapper)

@Autowired注入属性的逻辑在该方法里执行。— 我觉得这里应该是依赖注入的精髓。
这块代码的逻辑大致如下:

(1)假如当前bean里要@Autowired的属性在IOC容器里已经存在了,即这个属性先于当前bean被注入到了IOC容器 —> spring会在populateBean方法的具体实现里直接将该属性设置到当前bean里—>从而完成属性的注入。


(2)但是假如当前bean里要@Autowired的属性还没被注入到IOC容器 —> spring会在populateBean方法的具体实现里调用生成要@Autowired的属性对象的方法,让要@Autowired的属性对象先进行创建+初始化+注入到IOC容器 —> 然后再将要@Autowired的属性对象注入到当前bean。

总之一句话:在执行完populateBean(beanName, mbd, instanceWrapper)方法,当前bean里要@Autowired的属性已经全部被注入到了当前bean对象里。


3.2.2 initializeBean(beanName, exposedObject, mbd);

这块源码其实我在另一篇文章《【spring】详解InitializingBean、initMethod和@PostConstruct》里进行解读过,这里也将其骨干给抽出来:
在这里插入图片描述


3.2.2.1 applyBeanPostProcessorsBeforeInitialization方法

代码很简单,简单进行一下分析:

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		//获取到所有的BeanPostProcessor,
		//并拿着当前bean将所有的processor.postProcessBeforeInitialization方法遛一遍
		//如果当前bean满足某个processor.postProcessBeforeInitialization方法的条件,就会执行具体的逻辑
		//并返回执行结果后的bean,
		//如果没满足的话就在该processor.postProcessBeforeInitialization方法里遛一圈直接返回
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

3.2.2.2 invokeAwareMethods(beanName, bean)方法

就是执行InitializingBean、initMethod或@PostConstruct对应的方法
可以参看我的另一篇文章 — 《【spring】详解InitializingBean、initMethod和@PostConstruct》。


3.2.2.3 applyBeanPostProcessorsAfterInitialization方法

源码如下,几乎和applyBeanPostProcessorsBeforeInitialization的具体实现方法一样,也是获取到所有的BeanPostProcessor ,然后拿着当前bean,将所有的processor.postProcessAfterInitialization方法遛一遍,下面就不多过进行标注了。

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

4 两句话总结

(1)★★★populateBean(beanName, mbd, instanceWrapper)方法之后, @Autowired相关的属性注入已经全部完成
(2)可以借助initializeBean(beanName, exposedObject, mbd)方法完成bean的额外或者说特殊属性注入,这里又包括三种方式,其实更确切来说是三个时机:

  • 前置处理
  • 执行InitializingBean、initMethod或@PostConstruct对应的初始化方法
  • 后置处理
发布了189 篇原创文章 · 获赞 187 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/103192081
今日推荐