纵有疾风起
人生不言弃

【Spring 学习系列】Bean 的生命周期之初始化与销毁

一、背景

本文将结合一个简单案例,学习 Bean 生命周期中的初始化和销毁阶段的具体内容。
【Spring 学习系列】Bean 的生命周期之初始化与销毁插图

二、案例

Bean 的定义

package org.example.lifecycle.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class SomeBean implements InitializingBean, DisposableBean { 

    private Integer value;
    public  SomeBean(){ 
        System.out.println("构造方法");
    }

    public void setValue(Integer value) { 
        System.out.println("setValue:" + value);
        this.value = value;
    }

    public void open() { 
        System.out.println("init-method - 执行 ...");
    }

    public void close() { 
        System.out.println("destroy-method - 执行 ...");
    }

    @PostConstruct
    public void postConstruct() { 
        System.out.println("@PostConstruct - 执行 ...");
    }

    @PreDestroy
    public void preDestroy() { 
        System.out.println("@PreDestroy - 执行 ...");
    }


    @Override
    public void afterPropertiesSet() { 
        System.out.println("InitializingBean#afterPropertiesSet");
    }

    @Override
    public void destroy() { 
        System.out.println("DisposableBean#destroy");
    }
}

如果想要 @PostConstruct@PreDestroy 生效,可以使用@Component 注解,代替 xml 的方式。

配置信息

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.example.lifecycle.bean.SomeBean"
          init-method="open" destroy-method="close">
        <property name="value" value="1"/>
    </bean>
</beans>

测试代码

package org.example.lifecycle;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifecycleApplication { 

    public static void main(String[] args) { 
        System.out.println("准备初始化IOC容器。。。");
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("lifecycle/bean-initmethod.xml");
         //AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(LifeCycleConfiguration.class);
        System.out.println("IOC容器初始化完成。。。");
        System.out.println();
        System.out.println("准备销毁IOC容器。。。");
        ctx.close();
        System.out.println("IOC容器销毁完成。。。");
    }
}

执行结果:

准备初始化IOC容器。。。
构造方法
setValue:1
InitializingBean#afterPropertiesSet
init-method – 执行 …
IOC容器初始化完成。。。

准备销毁IOC容器。。。
DisposableBean#destroy
destroy-method – 执行 …
IOC容器销毁完成。。。

图示:
【Spring 学习系列】Bean 的生命周期之初始化与销毁插图1

三、分析

先猜想后验证:实例化、属性填充、初始化、销毁。具体是实现接口的初始化方法先执行还是自定义的初始化方法先执行需要看代码。

我们采用断掉调试法来分析学习,对每个方法打上断点,进行调试。

【1】执行到构造方法

【Spring 学习系列】Bean 的生命周期之初始化与销毁插图2

【2】执行到 setValue 方法
【Spring 学习系列】Bean 的生命周期之初始化与销毁插图3

【3】执行到 InitializingBean#afterPropertiesSet 方法

【Spring 学习系列】Bean 的生命周期之初始化与销毁插图4

【4】执行到 init-method

【Spring 学习系列】Bean 的生命周期之初始化与销毁插图5

核心方法 AbstractApplicationContext#refresh

@Override
	public void refresh() throws BeansException, IllegalStateException { 
		synchronized (this.startupShutdownMonitor) { 
		    // Prepare this context for refreshing.
			//1 初始化前的准备
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//2 获取 BeanFactory,加载所有 bean 的定义信息(未实例化)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 3 BeanFactory 的预处理配置
			prepareBeanFactory(beanFactory);

			try { 
				// Allows post-processing of the bean factory in context subclasses.
				// 4. 准备 BeanFactory 完成后进行的后置处理
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				 // 5. 执行 BeanFactory 创建后的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 6. 注册 Bean 的后置处理器
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 7. 初始化MessageSource
				initMessageSource();

				// Initialize event multicaster for this context.
				 // 8. 初始化事件派发器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				 // 9. 子类的多态 onRefresh
				onRefresh();

				// Check for listener beans and register them.
				 // 10. 监听器检查和注册
				registerListeners();
                // ------- BeanFactory已创建完成 --------

				// Instantiate all remaining (non-lazy-init) singletons.
				 // 11. 初始化所有剩下的单例Bean(非懒加载的)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event. 
				// 12. 完成容器的创建工作(发布相应的事件)
				finishRefresh();
			}

			catch (BeansException ex) { 
				if (logger.isWarnEnabled()) { 
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				// 销毁已经创建的单例避免浪费资源
				destroyBeans();

				// Reset 'active' flag.
				// 重置 active 标记
				cancelRefresh(ex);

				// Propagate exception to caller.
				// 异常抛给调用方
				throw ex;
			}

			finally { 
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				//13 清理缓存
				resetCommonCaches();
			}
		}
	}
@Override
	public void refresh() throws BeansException, IllegalStateException { 
		synchronized (this.startupShutdownMonitor) { 
		    // Prepare this context for refreshing.
			//1 初始化前的准备
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//2 获取 BeanFactory,加载所有 bean 的定义信息(未实例化)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 3 BeanFactory 的预处理配置
			prepareBeanFactory(beanFactory);

			try { 
				// Allows post-processing of the bean factory in context subclasses.
				// 4. 准备 BeanFactory 完成后进行的后置处理
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				 // 5. 执行 BeanFactory 创建后的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 6. 注册 Bean 的后置处理器
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 7. 初始化MessageSource
				initMessageSource();

				// Initialize event multicaster for this context.
				 // 8. 初始化事件派发器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				 // 9. 子类的多态 onRefresh
				onRefresh();

				// Check for listener beans and register them.
				 // 10. 监听器检查和注册
				registerListeners();
                // ------- BeanFactory已创建完成 --------

				// Instantiate all remaining (non-lazy-init) singletons.
				 // 11. 初始化所有剩下的单例Bean(非懒加载的)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event. 
				// 12. 完成容器的创建工作(发布相应的事件)
				finishRefresh();
			}

			catch (BeansException ex) { 
				if (logger.isWarnEnabled()) { 
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				// 销毁已经创建的单例避免浪费资源
				destroyBeans();

				// Reset 'active' flag.
				// 重置 active 标记
				cancelRefresh(ex);

				// Propagate exception to caller.
				// 异常抛给调用方
				throw ex;
			}

			finally { 
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				//13 清理缓存
				resetCommonCaches();
			}
		}
	}

【1】实例化、【2】属性填充、【3】afterPropertiesSet、【4】自定义 init 方法 都在 步骤 11 。

核心方法:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException { 

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) { 
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) { 
            
            //【1】 实例化:执行构造方法
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) { 
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) { 
			if (!mbd.postProcessed) { 
				try { 
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) { 
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) { 
			if (logger.isTraceEnabled()) { 
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try { 
            //【2】属性填充:执行到 setValue
			populateBean(beanName, mbd, instanceWrapper);
            
            //【3】初始化 Bean: 执行到 InitializingBean#afterPropertiesSet
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) { 
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 
				throw (BeanCreationException) ex;
			}
			else { 
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) { 
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) { 
				if (exposedObject == bean) { 
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) { 
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) { 
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try { 
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) { 
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

核心方法 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { 
		if (System.getSecurityManager() != null) { 
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else { 
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) { 
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try { 
            // 步骤【3】和【4】
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) { 
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) { 
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

核心方法 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable { 

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 
			if (logger.isTraceEnabled()) { 
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) { 
				try { 
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) { 
					throw pae.getException();
				}
			}
			else { 
                //【3】调用初始化方法: 执行 InitializingBean#afterPropertiesSet
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) { 
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) { 
                //【4】调用初始化方法: 调用自定义的 init 方法
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

【5】 执行到 DisposableBean#destroy 销毁方法

【Spring 学习系列】Bean 的生命周期之初始化与销毁插图6

【6】执行到自定义的 destroy 销毁方法

【Spring 学习系列】Bean 的生命周期之初始化与销毁插图7

核心方法:org.springframework.context.support.AbstractApplicationContext#close

	/** * Close this application context, destroying all beans in its bean factory. * <p>Delegates to {@code doClose()} for the actual closing procedure. * Also removes a JVM shutdown hook, if registered, as it's not needed anymore. * @see #doClose() * @see #registerShutdownHook() */
	@Override
	public void close() { 
		synchronized (this.startupShutdownMonitor) { 
            //1 执行关闭逻辑
			doClose();
            
			//2 由于已经关闭了上下文, shutdownHook 不再需要,移除掉
			if (this.shutdownHook != null) { 
				try { 
					Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
				}
				catch (IllegalStateException ex) { 
					// ignore - VM is already shutting down
				}
			}
		}
	}

核心方法 org.springframework.beans.factory.support.DisposableBeanAdapter#destroy

	@Override
	public void destroy() { 
		if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { 
			for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { 
				processor.postProcessBeforeDestruction(this.bean, this.beanName);
			}
		}

		if (this.invokeDisposableBean) { 
			if (logger.isTraceEnabled()) { 
				logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
			}
			try { 
				if (System.getSecurityManager() != null) { 
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 
						((DisposableBean) this.bean).destroy();
						return null;
					}, this.acc);
				}
				else { 
                    //【5】执行到 DisposableBean#destroy
					((DisposableBean) this.bean).destroy();
				}
			}
			catch (Throwable ex) { 
				String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
				if (logger.isDebugEnabled()) { 
					logger.warn(msg, ex);
				}
				else { 
					logger.warn(msg + ": " + ex);
				}
			}
		}

		if (this.destroyMethod != null) { 
            //【6】执行到 自定义的 destroy 方法
			invokeCustomDestroyMethod(this.destroyMethod);
		}
		else if (this.destroyMethodName != null) { 
			Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
			if (methodToInvoke != null) { 
				invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
			}
		}
	}

四、总结

本文主要使用猜想和验证的方法,代码调试的方法来学习 Bean 的生命周期之初始化和销毁。

创作不易,如果本文对你有帮助,欢迎点赞、收藏加关注,你的支持和鼓励,是我创作的最大动力。
【Spring 学习系列】Bean 的生命周期之初始化与销毁插图8

原文链接:https://mingmingruyue.blog.csdn.net/article/details/126313858

本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。

未经允许不得转载:起风网 » 【Spring 学习系列】Bean 的生命周期之初始化与销毁
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录