8-Spring源码解析之refresh(2)——【prepareRefresh】与【ConfigurableListableBeanFactory】

上一篇:Spring源码解析之refresh(1)——概览

上一篇介绍了refresh方法的概览,其中包含12个方法,接下来我们就依照顺序依次聊一下每个方法所实现的功能以及如何实现的。这篇文章先介绍【prepareRefresh】与【ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()】。

1. prepareRefresh方法

	protected void prepareRefresh() {
		// 记录容器启动的事件.
		this.startupDate = System.currentTimeMillis();
		// 设置对应的标志位
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// 扩展方法:本文使用的是AnnotationConfigApplicationContext进行创建容器因此在这里这个方法为空实现
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		// 这里我没有用到,所以暂时也没有具体看是做什么的,后续再补充吧!
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

这个方法也比较简单。

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 刷新容器  2.1节介绍
		refreshBeanFactory();
		// 返回beanFactory  2.2节介绍
		return getBeanFactory();
	}

2.1 refreshBeanFactory()

	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}

这个方法就实现一个功能:为beanFactory设置一个序列化Id

2.2 getBeanFactory()

	public final ConfigurableListableBeanFactory getBeanFactory() {
		return this.beanFactory;
	}

这里为什么还要在refresh里面再获取一下beanFactory呢? 答案有点绕,

回顾一下在第一篇文章:Spring容器创建之this()(1)——AnnotatedBeanDefinitionReader中,我们在this()里面,由于AnnotationConfigApplicationContext类的父类是GenericApplicationContext类,因此在有参构造器中调用this()时,首先执行父类GenericApplicationContext类的构造器,然后
再执行GenericApplicationContext类的父类AbstractBeanFactory的构造器。其中在调用GenericApplicationContext类的构造器的时候,执行的是:

	private final DefaultListableBeanFactory beanFactory;
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

而在本篇文章2.1节中 refresh方法所在的类为:AbstractApplicationContext,他是GenericApplicationContext的父类,因此无法获取GenericApplicationContext中的beanFactory,我们只能再调用refreshBeanFactory方法使得AbstractApplicationContext拥有beanFactory。为了方便理解AbstractApplicationContextGenericApplicationContextAnnotationConfigApplicationContext之间的关系,下面给出类图
在这里插入图片描述

3. 总结

  1. prepareRefresh方法:刷新前的预处理工作
  2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory():将this()方法中创建的beanFactory暴露给refresh方法所在的AbstractApplicaitonContext类,这样该类中refresh方法里的其他方法才可以使用beanFactory
发布了397 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/xiaojie_570/article/details/104618401
今日推荐