欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 Spring 系列——Bean生命周期

程序员文章站 2024-01-24 23:11:46
贴一张总的图说明代码执行流程看源码入口方法:getBeandoCreateBean关键的三个方法:createBeanInstance:实例化对象通过反射实现populateBean:设置对象属性实现了InstantiationAwareBeanPostProcessor接口 执行方法initializeBean:对象初始化完成后回调↓实现了Aware接口的回调BeanNameAwareBeanClassLoaderAwareBeanFactoryAwareBeanPo...

上篇文章《Spring 系列——IOC容器初始化》中我们介绍了Spring IOC容器初始化的过程,主要过程分为三个步骤:

  • 解析配置文件,组装成BeanDefinition对象
  • BeanDefinition注册到容器中
  • 对单例非懒加载Bean进行实例化

容器初始化完毕后,我们就能通过getBean()方法从容器中获取Bean实例。
对于单例非懒加载的Bean,容器在第三步中已经进行了实例化,getBean直接能取到实例对象
对于其他Bean,容器还未进行实例化,getBean()方法会先实例化Bean,然后再返回实例对象。本篇文章就对Bean在容器中的生命周期进行介绍。

注意:Spring容器只负责管理单例Bean(scope=singleton)的生命周期;对于多例Bean(scope=prototype),只负责创建,交给使用者之后就不会管理其生命周期

如果文章中有描述错误或者不合理的地方,欢迎指正!

开门见山

废话不多说,直接上图,让我们从宏观的视角去感受一下Bean在容器里发生了什么
荐
                                                        Spring 系列——Bean生命周期
从上图中,我们看到Spring 容器中 Bean从创建到销毁,有5个主干流程:

  • 构造 Bean 对象
  • 设置 Bean 属性
  • 初始化回调
  • Bean 调用
  • 销毁 Bean

左侧图例标识了关键源码的位置,方便大家自己去看源码,下面是对源码关键代码的说明

  • createBeanInstance:通过反射API创建Bean对象
  • populateBean:如果Bean有依赖属性,则会设置属性;如果是依赖对象,则会先实例化依赖的对象
  • initializeBean:Bean初始化回调
    • invokeAwareMethods:调用实现了*Aware接口中的方法
      • 如果Bean实现了BeanNameAware接口,调用setBeanName设置Bean的名称
      • 如果Bean实现了BeanClassLoaderAware,调用setBeanClassLoader设置Bean的类加载器
      • 如果Bean实现了BeanFactoryAware,调用setBeanFactory设置Bean的容器
    • applyBeanPostProcessorsBeforeInitialization:初始化前置增强,如果注册了BeanPostProcessor,调用postProcessBeforeInitialization,在Bean初始化前执行
    • invokeInitMethods:调用初始化方法
      • 如果Bean实现了InitializingBean接口,调用afterPropertiesSet,执行初始化
      • 如果配置文件中Bean定义包含了init-method属性,则调用相应的方法
    • applyBeanPostProcessorsAfterInitialization:初始化后置增强,如果注册了BeanPostProcessor,调用postProcessAfterInitialization,在Bean初始化后执行
  • Bean初始化完成,可以被调用
  • 销毁Bean
    • 如果Bean实现了DisposableBean接口,当容器不再需要Bean引用时,执行destory销毁Bean
    • 如果配置文件中Bean定义包含了destory-method属性,则调用相应的方法

小试牛刀

下面我们通过一个Demo来演示一下Bean完整的生命周期,加深大家的印象

  • 我们定义一个LifeService类,实现下面6个接口:BeanNameAwareBeanClassLoaderAwareBeanFactoryAwareInitializingBeanDisposableBeanApplicationContextAware接口;同时自定义init-methoddestory-method方法。如果不了解这几个接口,大家可以去阅读源码了解一下,这里就不展开了
public class LifeService implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware,
		InitializingBean, DisposableBean, ApplicationContextAware {

	private String name;

	public void setName(String name) {
		System.out.println("设置属性");
		this.name = name;
	}

	public LifeService() {
		System.out.println("构造方法");
	}

	public void myInit(){
		System.out.println("init-method自定义初始化方法");
	}

	public void myDestory(){
		System.out.println("destroy-method自定义销毁方法");
	}

	public void printMessage(){
		System.out.println("======执行业务逻辑 printMessage=====");
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		System.out.println("setBeanClassLoader");
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("setBeanFactory");
	}

	@Override
	public void setBeanName(String name) {
		System.out.println("setBeanName");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("初始化init afterPropertiesSet");
	}

	@Override
	public void destroy() throws Exception {
		System.out.println("destroy");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println("setApplicationContext");
	}
}
  • 定义一个MyBeanPostProcessor实现BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("Before postProcessBeforeInitialization");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("After postProcessAfterInitialization");
		return bean;
	}
}
  • 配置xml配置文件,指定init-method和destroy-method属性
<bean id="lifeService" class="com.dev.domain.LifeService" init-method="myInit" destroy-method="myDestory">
	<property name="name" value="muskmelon"/>
</bean>

<!--自定义后置处理器-->
<bean id="postProcessor" class="com.dev.domain.MyBeanPostProcessor"/>
  • 启动容器,执行业务逻辑,销毁容器
public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
	LifeService lifeService = (LifeService) context.getBean("lifeService");
	lifeService.printMessage();
	((ClassPathXmlApplicationContext) context).close();
}
=======执行结果=======
构造方法
设置属性,name=muskmelon
setBeanName
setBeanClassLoader
setBeanFactory
setApplicationContext
Before postProcessBeforeInitialization
初始化init afterPropertiesSet
init-method自定义初始化方法
After postProcessAfterInitialization
======执行业务逻辑 printMessage=====
destroy
destroy-method自定义销毁方法

可以看到执行结果和我们描述的基本一致,我们前面说了BeanPostProcessor是在Bean生命周期中的调用执行,但是它是什么时候注册到容器中的呢?我们就得翻出讲IOC容器初始化的这篇文章了,详细请看《Spring 系列——IOC容器初始化》

庖丁解牛

我们直接看refresh方法的源码吧

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		prepareRefresh();
	
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
	
		prepareBeanFactory(beanFactory);
	
		try {
			postProcessBeanFactory(beanFactory);
	
			invokeBeanFactoryPostProcessors(beanFactory);
			// 【看这里】注册BeanPostProcessor的实现类
			// 接口提供两个方法:postProcessBeforeInitialization 和 postProcessAfterInitialization
			// 这两个方法分别在初始化前后执行
			registerBeanPostProcessors(beanFactory);
			
			//下面的省略
			......
	}
}

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
	// 1.获取容器中继承了BeanPostProcessor接口的子类的beanName集合
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

	// 注册BeanPostProcessorChecker,用于校验一个Bean在实例化的过程中,能成功的执行所有的BeanPostProcessor后置处理,如果有一个失败,则会打印相关日志
	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// 2.将BeanPostProcessor根据实现的排序接口分类,分为3类:PriorityOrdered,Ordered,nonOrdered
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	for (String ppName : postProcessorNames) {
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);
		}
	}

	// 3. 注册 priorityOrderedPostProcessors
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
	// 4.注册 orderedPostProcessors
	sortPostProcessors(orderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);

	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	for (String ppName : nonOrderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		nonOrderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
	// 5.注册 nonOrderedPostProcessors
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

	// 6.注册 internalPostProcessors
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);

	// 7.注册ApplicationListenerDetector
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

我们看到registerBeanPostProcessors方法的作用就是将BeanPostProcessor注册到容器。细心的读者可能看到我们的示例代码中还实现了一个ApplicationContextAware 接口,其实这是在ApplicationContextAwareProcessor处理器中执行的,这也是BeanPostProcessor的子类,但是上面源码中注册了众多的BeanPostProcessor,并没有对ApplicationContextAwareProcessor进行注册,那它是在哪里注册的呢?
其实也是在容器初始化的过程中进行注册的,我们看refresh方法的prepareBeanFactory方法

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// ...省略
	
	// 【看这里】
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
	
	// ....省略
	
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));


	if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}

	// ...省略
}

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)) 注册了容器上下文的增强处理器,除了对实现ApplicationContextAware接口的Bean进行处理,如果Bean还实现了以下接口也会进行调用:EnvironmentAwareEmbeddedValueResolverAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAware,具体的用途就不展开了,有兴趣的读者可以自行查阅资料。

private void invokeAwareInterfaces(Object bean) {
	if (bean instanceof EnvironmentAware) {
		((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
	}
	if (bean instanceof EmbeddedValueResolverAware) {
		((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
	}
	if (bean instanceof ResourceLoaderAware) {
		((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
	}
	if (bean instanceof ApplicationEventPublisherAware) {
		((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
	}
	if (bean instanceof MessageSourceAware) {
		((MessageSourceAware) bean).setMessageSource(this.applicationContext);
	}
	if (bean instanceof ApplicationContextAware) {
		((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
	}
}

抛砖引玉

上面我们讲述的都是ApplicationContext中Bean的生命周期,那么BeanFactory中Bean的生命周期是否有什么不同呢?
示例代码仍然使用上面的,贴一下使用BeanFactory来注册Bean的代码

public static void main(String[] args) {
	DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
	XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	xmlBeanDefinitionReader.loadBeanDefinitions(new ClassPathResource("spring.xml"));
	beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
	LifeService lifeService2 = (LifeService)beanFactory.getBean("lifeService");
	lifeService2.printMessage();
	beanFactory.destroySingletons();
}
=======执行结果=======
构造方法
设置属性
setBeanName
setBeanClassLoader
setBeanFactory
Before postProcessBeforeInitialization
初始化init afterPropertiesSet
init-method自定义初始化方法
After postProcessAfterInitialization
======执行业务逻辑 printMessage=====
destroy
destroy-method自定义销毁方法

对比上面的结果,我们看到执行代码中BeanPostProcessor是通过手动注册,执行结果中没有输出setApplicationContext,这是为什么呢?

在了解Spring IOC容器初始化的流程后,我们知道ApplicationContext是BeanFactory的子类,它在初始化的过程中(refresh方法),除了读取配置文件,解析成BeanDefinition,并注册到容器中之外,还做了诸多用于扩展Bean的功能,比如:注册BeanPostProcessor,实例化单例非懒加载Bean,注册BeanFactoryPostProcessor等等,不清楚的可以再回过头去看看容器初始化的流程,温故而知新。

BeanFactory 是Spring容器最顶端的接口类,提供了配置框架和基础功能,ApplicationContext添加了更多企业级功能。所以像BeanPostProcessor诸如此类的功能就需要我们自己手动配置,没有注册过ApplicationContextAwareProcessor,就自然不会打印setApplicationContext

综上所述

至此,Spring Bean生命周期的流程我们讲完了,我们来一起总结以下:

  • Spring 容器只管理单例Bean的生命周期,prototype类型的Bean创建完成后,其生命周期就丢给使用者自己处理(一般就是通过GC进行回收了)
  • Bean生命周期关键步骤:创建Bean对象,设置Bean属性,初始化回调,调用Bean,销毁Bean
  • Spring 容器中通过注册BeanPostProcessor,在Bean初始化前后,对Bean实例进行特殊处理;我们也可以通过自定义BeanPostProcessor来实现Bean的扩展功能
  • ApplicationContext中Bean的生命周期和BeanFactory中Bean的生命周期区别
    (1)BeanFactory容器中不会调用setApplicationContext方法
    (2)BeanFactory容器中BeanPostProcessor需要手动注册
    (3)BeanFactory容器启动时不会去实例化所有Bean,包括单例非懒加载的bean,而是在调用的时候去实例化。

本文地址:https://blog.csdn.net/czxlylc/article/details/107104197