spring bean生命周期管理

本文详细介绍了Spring框架中Bean的生命周期,从bean的来源与发展、bean的定义,到bean实例化、属性赋值、初始化和销毁的过程。文章结合源码探讨了Spring如何管理bean,包括bean的创建前流程、初始化、属性注入和自定义初始化方法的执行。此外,还讲解了单例bean的销毁方法注册和调用。通过对Spring Bean生命周期的深入理解,有助于更好地掌握Spring框架的使用。
摘要由CSDN通过智能技术生成

spring bean生命周期,spring框架老生常谈的话题,也是spring的基础知识。借此篇文章,结合spring框架部分源码,对spring针对bean的生命周期管理进行一个总结,加深记忆。

1. 概述

1.1 何为bean

在讲解bean的周期之前,我们先了解下什么是bean。自我们接触java开始,bean就无处不在。那么bean是什么?这里有两种解释,一种是狭义的,一种是广义的。在解释前,先简单介绍下bean的历史背景。

1.1.1 bean的来源与发展

在java诞生后不久,开发者为了让java更适用于桌面开发,借鉴vb等语言的特点,准备开发一套可视化ide。为了方便开发这款ide,开发者们为java定义了一套类定义规范:

	1. 是public,有无参构造器
	2. 有private属性
	3. 有get/set方法,对属性进行访问和修改
	4. 要能支持事件,如onClickListener等等
	5. 要可序列化
	6. ...
	7. ...

这个规范就叫做bean,基于这个规范,sun公司推出了NetBeans IDE并风靡一时,直到后来,IBM推出了Visual Age for Java,Visual Age for Java就是eclipse的前身。

javabean的出现给java带来革命性的改变,但是依然没有人使用java进行桌面开发。直到在web开发领域,java才真正找到了自己的用武之地。javabean也没有被抛弃,人们将javabean作为数据传输介质,将控制器层(controller)和展示层(view)串联起来,这就是mvc框架。

在企业开发中当然不是这么简单,企业开发中可能需要事务、需要消息处理、需要分布式等等,为了满足企业开发要求,sun公司推出了J2EE规范,这个规范基本涵盖了java在web开发中的方方面面,如JDBC(Java Database Connectivity)、JDNI(Java Naming and Directory Interface)、JTA(Java Transaction API)等,还有最重要的,在javabean的基础之上,推出了EJB(Enterprise Java Beans),EJB规范因为可以无缝衔接其他规范,从而让开发人员无需关注事务处理、安全处理等琐碎的技术细节,所以在web开发中盛行起来。

随着互联网领域的规模越来越大,需求越来越多,迭代的速度越来越快,人们发现EJB已经无法适应当前的潮流,太繁琐、太笨重,人们开始给EJB进行瘦身,POJO(Plain Old Java Object)就诞生了。POJO摒弃了大部分EJB bean的规范,仅保留了简单的几条:

1. 是public,有无参构造器
2. 有private属性
3. 有get/set方法,对属性进行访问和修改
4. 可序列化

虽然抛弃了EJB,但是我们也想在使用POJO的时候?大神Rod Johnson推出了spring。通过将POJO委托给spring框架进行管理,我们依然可以实现在EJB时代的功能。当然,在spring生态中,不仅POJO是bean,被spring容器所管理的任意一个对象,都可以被称作bean。

spring的出现彻底改变了java开发圈子,所有人(至少是web开发者)大都会选择spring作为自己开发的首要框架。随着spring全家桶的完善,java开发者与spring生态绑定的越来越紧密。

1.1.2 bean的定义

介绍完历史,我们再说下何为bean。上文说过,bean可以从狭义和广义两个角度去看:

  • 狭义的bean:即POJO或符合EJB规范的bean
  • 广义的bean:即被spring容器所管理的所有对象

接下来,本篇文章中所描述的bean,皆为广义的bean。

1.2 spring bean模型

spring对所有的bean进行了一个统一的抽象建模,即BeanDefinition,这里面包含了spring框架对bean的描述,如bean的class、bean的作用域、bean的依赖bean、bean是否是懒加载、bean的构造方法参数等等。spring通过这些信息,才能准确、无误、高效地管理一个bean。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
   
	// 获取bean类名
	@Nullable
	String getBeanClassName();
	// 获取bean的作用域
	@Nullable
	String getScope();
	// 是否懒加载
	boolean isLazyInit();
	// 获取bean前置依赖的bean
	@Nullable
	String[] getDependsOn();
	// 获取bean构造方法参数
	ConstructorArgumentValues getConstructorArgumentValues();
	// 获取bean的属性参数
	MutablePropertyValues getPropertyValues();
	...

1.3 bean创建前的流程

在spring容器启动后,会去扫描和解析我们配置的bean,包括注解和xml等方式配置的(扫描、解析过程这里暂不介绍)
并校验、创建BeanDefinition,并交给BeanDefinitionHolder持有:

public class BeanDefinitionHolder implements BeanMetadataElement {
   

	private final BeanDefinition beanDefinition;
	// bean名称
	private final String beanName;
	// bean的别名
	@Nullable
	private final String[] aliases;
		...

到目前为止,spring并没有实例化任何一个bean,仅仅根据我们配置的信息创建了一个个BeanDefinition,这里也体现了spring框架的基于元配置的编程思想。

以spring读取xml配置文件为例(注解配置细节有所不同,但基本流程是相似的):
spring容器(这里是ClassPathXmlApplicationContext)启动时会去创建DefaultListableBeanFactory

	/**
	 * This implementation performs an actual refresh of this context's underlying
	 * bean factory, shutting down the previous bean factory (if any) and
	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
	 */
	@Override
	protected final void refreshBeanFactory() throws BeansException {
   
		if (hasBeanFactory()) {
   
			destroyBeans();
			closeBeanFactory();
		}
		try {
   
			// 创建bean管理工厂
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			// 加载Bean配置
			loadBeanDefinitions(beanFactory);
			...

DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,并持有所有注册的BeanDefinition

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
   
		...
			/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
		...

ClassPathXmlApplicationContext会创建XmlBeanDefinitionReader去加载bean

/**
	 * Loads the bean definitions via an XmlBeanDefinitionReader.
	 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
	 * @see #initBeanDefinitionReader
	 * @see #loadBeanDefinitions
	 */
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		// 使用xmlBeanDefinitionReader去加载配置的bean
		loadBeanDefinitions(beanDefinitionReader);
	}

XmlBeanDefinitionReader会对我们提供的xml配置文件进行解析、校验等工作,然后遍历xml配置文件的每一个节点:

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
   
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
   
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
   
		    // 如果节点的标签是bean,则加载该节点所配置的bean数据
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
   
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

bean节点会被解析然后注册到DefaultListableBeanFactory

/**
	 * Process the given bean element, parsing the bean definition
	 * and registering it with the registry.
	 */
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   
	// 根据节点的配置,创建好BeanDefinitionHolder
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
   
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
   
				// 将解析好的节点注册到DefaultListableBeanFactory当中
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
   
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

这里的代码进行实际的注册:

/**
	 * Register the given bean definition with the given bean factory.
	 * @param definitionHolder the bean definition including name and aliases
	 * @param registry the bean factory to register with
	 * @throws BeanDefinitionStoreException if registration failed
	 */
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {
   

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		// 注册bean
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
   
			for (String alias : aliases) {
   
				registry.registerAlias(beanName, alias);
			}
		}
	}

bean的注册还涉及到大段解析配置、校验逻辑,这里就不赘述了。上述代码得到的最终结果是,spring通过我们在xml文件中配置的bean创建了BeanDefinition,至此,bean实例化的前置工作完成。

1.4 spring bean生命周期

spring bean被注册后,其生命周期才算正式开始。与普通的javabean生命周期不同,spring将bean的生命周期划分的更为细致,并且添加了多个扩展点(著名的BeanPostProcessor接口),方便开发人员对bean的生命周期进行自定义扩展。上个图吧:

普通javabean生命周期

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值