【Spring源码系列(一)】Bean的生命周期

Spring 中 Bean 的生命周期

1,什么是 Bean?

凡是由 Spring IoC 容器负责实例化,组装和管理的对象,我们都称之为 Bean 对象。Bean 对象本身可以看做是 Pojo。

官网解释:

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

2,Bean 的生命周期

image-20210913125107850

2.1,BeanDefinition 读取&解析

我们可以通过 XML 或者是配置注解的方式为 Bean 进行配置。该阶段由 BeanDefinitionReader 接口负责,并由其实现类具体实现。

image-20210911162504718

另一方面,Spring 的配置文件读取是通过 Resource 接口定义:

image-20210911165210092

总结:文件解析流程

  • 获取对 XML 文件的验证模式;(DTD 和 XSD 方式,文件头注明)
  • 加载 XML 文件,获得对应的 Doucument;
  • 根据 Document 注册 Bean 信息。

2.2,BeanDefinition 注册&加载

通过上述方式我们获得 Document 后解析为 BeanDefinition,通过 BeanDefinitionRegistry 的唯一真正实现子类 DefaultListableBeanFactory#registerBeanDefinition 注册,并存储在 beanDefinitionMap 中。

同时,此过程中还涉及到 BeanDefinition 的合并与转换,比如将存在父子关系的 RootBeanDefinition 和 ChileBeanDefinition 通过

DefaultListableBeanFactory#getMergedBeanDefinition 方法合并为一个最终的 RootBeanDefinition。因为解析得到的 BeanDefinition 是以 GenericBeanDefinition 的形式而存在的,也要做一步转换。

何谓父子关系?也就是 bean 之间可以继承,子类享有父类的属性。

image-20210908211914787

有没有想想我们为什么需要 BeanDefinition,按道理我们需要的是 Bean 工厂。

其实,在 BeanDefinition 中有个 Object beanClass;通过 AbstractBeanFactory#resolveBeanClass 将 object 类型对象转换为 class 型以便后续进行实例化。

2.3,Bean 实例化

2.3.1,Bean 实例化前

实例化前,可以通过实现 BeanFactoryPostProcessor#postProcessBeanFactory,并根据优先级顺序对读取的 BeanDefinition 进行属性覆盖和增加。(注意不能提前获取 Bean 对象,会造成 Bean 的提前初始化。)

此过程相当于对 BeanFactory 的一个扩展。

2.3.2,Bean 实例化

image-20210912154930958
image-20210911192823752
image-20210912175005544
这个阶段会在实例 Bean 的过程中穿插涉及到 InstantiationAwareBeanPostProcessor 的较多操作,我们主要看下它的实现方法的调用机制。

首先,通过 AbstractAutowireCapableBeanFactory#createBean#doCreateBean#createBeanInstance 方法,同时对于不同的 Bean 会有不同的实例策略:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// BeanDefinition 加载获得类对象
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		//1,如果 factory-method 属性不为空,则使用 factory-method 方式实例化
		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);
			}
		}

		//2,决定候选的构造器实例化 bean...
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		//3, 否则指向默认的无参构造策略:
    	   //最终通过 BeanUtils#instantiateClass 调用 ctor.newInstance 方法反射创建
		return instantiateBean(beanName, mbd);
	}

当然,对于有依赖的 Bean,可以通过后置增强器实现依赖 Bean 的实例化,处理原则是先实现依赖的 Bean,再实例 Bean。

重点来了,在实例化阶段可以进行增强操作,具体通过 AbstractAutowireCapableBeanFactory#creatBean 方法中通过调用 resolveBeforeInstantiation 里的增强操作,如果返回不为空则直接完成 Bean 的实例化操作退出;如果返回为空,则进入上层的 createBean 方法执行 doCreateBean,继续完成 spring 正常的执行流程。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
			//省略。。。。。
try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
}

这里的 resolveBeforeInstantiation 分别进行了 applyBeanPostProcessorsBeforeInstantiation 和 applyBeanPostProcessorsAfterInitialization 实现实例化前和初始化后的增强操作。可见,如果在实例化前进行了增强,那么会跳过实例化后和初始化前操作,直接创建完成 Bean 对象。下一阶段将会进行属性填充。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

上面说道,当我们的 resolveBeforeInstantiation 返回为空的时候会正常执行对象的实例,doCreateBean 方法触发:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)	throws BeanCreationException {
	// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
            //如果 bean 实例未被创建,先创建 bean,这里调用 createBeanInstance 又回到了上面
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
// Initialize the bean instance.
		Object exposedObject = bean;
		try {
            		//属性赋值
			populateBean(beanName, mbd, instanceWrapper);
            		//initializeBean 进去便触发我们的初始化方法
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}

我们再来看 populateBean:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					//实例化后置处理器(属性赋值也被认为是实例化阶段)
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

小结:

BeanPostProcessor 定义的初始化前后方法,会在 resolveBeforeInstantiation 触发前置处理器;或是在 initializeBean 触发前置和后置处理器。

InstantiationAwareBeanPostProcessor 定义的方法,会在实例化过程中,由 resolveBeforeInstantiation 触发前置处理器,populateBean 触发后置处理器。

2.3.3,属性赋值

这一步进行属性填充,具体是 InstantiationAwareBeanPostProcessor#populateBean 里的 getPropertyValues。该方法最终会通过调用 Filed.set 方法完成 xml 中标签 property 配置的属性注入。

该方法的另外两个实现:

AutowiredAnnotationBeanPostProcessor 在这个方法对@Autowired、@Value 标注的字段、方法注入值。

CommonAnnotationBeanPostProcessor 在这个方法对@Resource 标注的字段和方法注入值。

2.4,Bean 初始化

2.4.1,Bean 初始化前

此过程对 AbstractAutowireCapableBeanFactory#initializeBea 中的调用顺序:

  • applyBeanPostProcessorsBeforeInitialization#postProcessBeforeInitialization 的前置处理器
  • invokeInitMethods #初始化方法
  • applyBeanPostProcessorsAfterInitialization#postProcessAfterInitialization 的后置处理器
2.4.2,Bean 初始化

调用 InitializingBean#afterPropertiesSet 方法;

然后调用定义 bean 的时候指定的初始化方法

Bean 知道初始化方法的方式:

方式 1:xml 方式指定初始化方法

方式 2:@Bean 的方式指定初始化方法

@Bean(initMethod = “初始化的方法”)

方式 3:api 的方式指定初始化方法

this.beanDefinition.setInitMethodName(methodName);

2.4.3,Bean 初始化后

调用 BeanPostProcessor 接口的 postProcessAfterInitialization 方法。

2.5,Bean 使用

直接调用 getBean 方法。

2.6,Bean 销毁

轮询 beanPostProcessors 列表,如果是 DestructionAwareBeanPostProcessor 这种类型的,会调用其内部的 postProcessBeforeDestruction 方法;

如果 bean 实现了 org.springframework.beans.factory.DisposableBean 接口,会调用这个接口中的 destroy 方法;

调用 bean 自定义的销毁方法。

3,面试

3.1,FactoryBean

某些时候实例化一个 Bean 非常复杂,如果他有较多的属性时,需要配置大量信息。而使用工厂BeanFactory创建bean的方式会严格执行生命周期,带来许多不便。为此可以通过实现 FactoryBean 接口定制实例化 Bean 逻辑。

当我们在配置文件中将 bean 的 class 属性设为 FactoryBean 接口类型时,通过 getBean 方法获取的 bean 不是 FactoryBean 本身而是 FactoryBean#getObject() 方法返回的对象,这里有一个代理。如果需要获取 FactoryBean 实例对象,需要显式的进行 getBean(&beanName)。
简而言之,FactoryBean是个小工厂,BeanFactory是个根工厂。

3.2,三级缓存解决循环依赖
	/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

image-20210911193815106

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值