飞道的博客

一张图让你读懂spring bean的生成过程

355人阅读  评论(0)

​​​​

目的:

不拘泥与具体细节,对spring bean的生成能有一个整体的把握。

图片整体预览

正文

spring bean的生成主要分为两个阶段,第一个是bean Definition的生成
,第二个是bean的生成。也就是本文的主要内容。
对于spring实例初始一个bean,我们主要分析一下几点

  • 子类beanDefinition合并父类bean Definition的一些数据;
  • bean实例化之前的操作介绍resolveBeforeInstantiation(产生代理的时机)
  • 实例化bean的几种方式 createBeanInstance
    • 工厂方法创建
    • 带参数的构造方法创建
    • 默认的构造方法创建
  • 注入数学过程如何解决循环依赖
  • bean实例化后属性的装填工作populateBean
    • 名称注入
    • 类型注入
  • 初始化bean initializeBean方法调用
    • 处理 bean 的前置处理器
    • 执行 init-method 方法
    • 处理 bean 的后置处理器
      以上几点是按照上图,方法的调用顺序依次介绍。也是bean生成过程的顺序介绍。

子类beanDefinition合并父类bean Definition的一些数据;

这块主要是图片中这部分的介绍
子类的bean因为是继承了父类bean,所以在创建子类时需要合并一些父类的属性到子类中,主要是getMergedLocalBeanDefinition()
这个方法不是很重要,这里就不贴源码占用大家时间了。

bean实例化之前的操作介绍resolveBeforeInstantiation(产生代理的时机)

这个小结主要介绍的是下图这块的内容

贴个入口代码

            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}

我们创建代理是通过一个后置处理器

实例化bean的几种方式 createBeanInstance

  • 工厂方法创建
  • 带参数的构造方法创建
  • 默认的构造方法创建
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		if (mbd.getFactoryMethodName() != null)  {//工厂方法创建
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}
		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);//带参数的构造方法创建
			}
			else {
				return instantiateBean(beanName, mbd);//默认的构造方法创建
			}
		}

bean实例化后属性的装填工作populateBean

属性的依赖注入就是在这个阶段,比如通过Autowire注入这种。同样我们这里重点分析循环依赖。

注入过程如何解决循环依赖

A依赖B、B依赖A 形成一个依赖环。spring的解决方案是,实例化A,之后将A封装到一个ObjectFactory对象中存储。对A进行属性填充的时候,发现有B需要实例化,则去实例化B,实例化B的时候也会将B封装到一个ObjectFactory对象中存储。B实例化完之后,会去填充B的属性,这是发现有A属性需要填充,这是不再会去创建A而是从封装了A对象的ObjectFactory中直接取。从而完成B的属性填充,继而完成了A的属性填充。更加完善的源码分析,可以参考文章

初始化bean initializeBean方法调用

  • 处理bean的前置处理器
  • 执行 init-method方法
  • 处理 bean的后置处理器
    这里要补充下bean的后置处理器,后置处理器在spring中是非常强大的,可以处理很多事。不仅仅是bean的初始化中对bean修改,同时在上一小节中的属性注入也是这通过autowireBeanPostProcessor进行注入。spring将很多小功能拆给了一个后置处理器来处理。系统就非常灵活了。

进入initializeBean的过程

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				//调用一些aware方法注入一些系统的属性到bean中
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
		//bean 前置处理
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
		//调用bean init方法
			wrappedBean = 
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
	
		if (mbd == null || !mbd.isSynthetic()) {
		//对bean进行一些后置处理
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

以上对于getBean的流程基本分析完,后序会征对spring的一些细节进一步深入分析。


转载:https://blog.csdn.net/ygy982883422/article/details/105758616
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场