AbstractRefreshableApplicationContext源码解析

本文深入探讨了Spring框架中AbstractRefreshableApplicationContext的源码,包括其在容器刷新中的作用,属性设置,如bean工厂的刷新和定制,以及关闭容器的相关操作。重点介绍了loadBeanDefinitions()方法在bean注册过程中的重要性,并强调了该类为容器刷新所做的准备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整体认识

在这里插入图片描述
先来看一下整体架构图。
从该类的名字可以看出来,是为了容器刷新而存在的
该类名称:可刷新的ApllicationContext容器抽象类。
每次刷新容器要干的事就是重新将bean注册到容器中,至于以哪样的策略来实现bean注册,这要具体看Spring如何实现的。其子类唯一实现的方法就是loadBeanDefinitions()方法。

具体认识

1. 属性

@Nullable
	// 是否允许bean定义被同名的bean定义覆盖
	private Boolean allowBeanDefinitionOverriding;
	// 是否允许循环引用标志位
	@Nullable
	private Boolean allowCircularReferences;

	/** Bean factory for this context. */
	// 当前容器Bean工厂
	@Nullable
	private volatile DefaultListableBeanFactory beanFactory;

两个标志的set方法,两个标志的默认是都是true,这里不再赘述。


	/**
	 * Set whether it should be allowed to override bean definitions by registering
	 * a different definition with the same name, automatically replacing the former.
	 * If not, an exception will be thrown. Default is "true".
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
	 */
	public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
		this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
	}

	/**
	 * Set whether to allow circular references between beans - and automatically
	 * try to resolve them.
	 * <p>Default is "true". Turn this off to throw an exception when encountering
	 * a circular reference, disallowing them completely.
	 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
	 */
	public void setAllowCircularReferences(boolean allowCircularReferences) {
		this.allowCircularReferences = allowCircularReferences;
	}

2. 刷新bean工厂

/**
	 * 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.
	 * ~~~~~~~~~~~~~~~~~~~~~~~~
	 * 此实现对该上下文的基础bean工厂执行实际的刷新
	 * 关闭前一个bean工厂(如果有),并为该上下文生命周期的下一阶段初始化一个新的bean工厂
	 * ~~~~~~~~~~~~~~~~~~~~~~~~
	 */
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		// 判断当前容器是够有Bean工厂,如果有的话直接关闭该bean工厂
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// 创建新的bean工厂,之前存在的已经关闭了
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 指定一个ID以进行序列化,这里指定的是容器id,如果需要的话
			// 允许将该BeanFactory从该ID反序列化回BeanFactory对象
			beanFactory.setSerializationId(getId());
			// 定制容器使用的内部bean工厂
			customizeBeanFactory(beanFactory);
			// 委托多个bean加载器,将bean定义加载到指定的bean工厂中
			loadBeanDefinitions(beanFactory);
			// bean工厂赋值
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

2.1 序列化bean工厂

/**
	 * Specify an id for serialization purposes, allowing this BeanFactory to be
	 * deserialized from this id back into the BeanFactory object, if needed.
	 * ~~~~~~~~~~~~~~~~~~~~~~~~~~
	 * 指定一个ID以进行序列化,如果需要的话,允许将该BeanFactory从该ID反序列化回BeanFactory对象
	 * ~~~~~~~~~~~~~~~~~~~~~~~~~~
	 */
	public void setSerializationId(@Nullable String serializationId) {
		if (serializationId != null) {
			serializableFactories.put(serializationId, new WeakReference<>(this));
		}
		else if (this.serializationId != null) {
			serializableFactories.remove(this.serializationId);
		}
		this.serializationId = serializationId;
	}

2.2 定制容器使用的内部bean工厂

看源码可知道也就是设置bean定义是否可覆盖和循环引用标志

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

关闭容器刷新和bean工厂

@Override
	// 关闭容器刷新
	protected void cancelRefresh(BeansException ex) {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory != null) {
			beanFactory.setSerializationId(null);
		}
		super.cancelRefresh(ex);
	}
	// 关闭bean工厂
	@Override
	protected final void closeBeanFactory() {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory != null) {
			beanFactory.setSerializationId(null);
			this.beanFactory = null;
		}
	}

获取bean工厂

@Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory == null) {
			throw new IllegalStateException("BeanFactory not initialized or already closed - " +
					"call 'refresh' before accessing beans via the ApplicationContext");
		}
		return beanFactory;
	}

至此所有重要的方法就了解完了

总结

这个类是简单的,但是要知道这个类的具体作用是什么。
由名字可以知道,该类主要是容器的刷新

  • 设置了标志位来决定是否覆盖bean定义和循环引用
  • 刷新容器肯定要重新定制bean工厂,定制bean工厂是该类的重要功能

该类的所有功能都是为了容器刷新做准备,至于容器刷新所需要读取配置文件,加载beanDefinition则是由AbstractRefreshableConfigApplicationContext来完成。Spring的优良做法就是看见类名就能大概知道该类的所提供的功能。

Spring IOC学习开始

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值