当前位置: 移动技术网 > IT编程>开发语言>Java > 荐 Spring 系列——Bean生命周期

荐 Spring 系列——Bean生命周期

2020年07月07日  | 移动技术网IT编程  | 我要评论

上篇文章《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从创建到销毁,有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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网