Spring前置准备(四)——获取工厂对象

部署运行你感兴趣的模型镜像

原本这章是要解析prepareRefresh中的这段代码的,但是没有找到earlyApplicationListeners对象在哪里应用了,查了下资料这部分逻辑应该是在prepareRefresh阶段出触发的,所以这里先跳过:

// 这个暂时不知道啥意思,我估计要往后面看才能明白
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<>();

那么继续,之后就是refresh方法的obtainFreshBeanFactory方法的解析了:

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

该方法具体内容如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
}

首先解析refreshBeanFactory方法,具体内容如下:

createBeanFactorycreateBeanFactory@Override
protected final void refreshBeanFactory() throws BeansException {
	// 如果bean工厂不等于空则销毁bean工厂
	// 判断bean工厂是否不等于空,如果不等于则销毁bean工厂
	if (hasBeanFactory()) {
	  // 这个方法我看了下,其实就是对工厂的各大容器进行clear方法的调用,实在想了解,可以在下面评论,我带大家看一看
	  // 不讲解的原因还有一个,由于是第一次创建工厂所以这里的工厂对象并不会有具体的实例,也就不会进入这个判断,我debug试过了
		destroyBeans();
		// 关闭bean工厂,不解析,原因同上
		closeBeanFactory();
	}
	try {
		// 创建DefaultListableBeanFactory
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory);
		loadBeanDefinitions(beanFactory);
		this.beanFactory = beanFactory;
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

前半段内容不是很复杂,看注释,这里提一句,看我的文章一定要看注释!!!看注释!!!看注释!!!重要的话说三遍!!!!,接下来就是createBeanFactory方法的解析了:

DefaultListableBeanFactory beanFactory = createBeanFactory();

createBeanFactory方法其实就是创建了一个DefaultListableBeanFactory对象:

protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

这个对象调用了getInternalParentBeanFactory方法,这个方法判断是否是ConfigurableApplicationContext如果是,则使用getBeanFactory方法获取工厂对象,否则调用getParent:

@Nullable
protected BeanFactory getInternalParentBeanFactory() {
	return (getParent() instanceof ConfigurableApplicationContext ?
			((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent());
}

那么这里提出一个问题,为什么要做以下判断呢:

getParent() instanceof ConfigurableApplicationContext

要理解这里我们首先要注意一个关键字:instanceof,这个关键字需要注意,如果一个对象的实际类型是某个类的子类,那么使用instanceof判断该对象是否为这个类的实例时,结果会为true,例如:B继承了A ,如果用instanceof判断B是否是A类型,会返回true,所以这里判断的是两种情况:

  1. 属于ConfigurableApplicationContext的所有子类对象(ConfigurableApplicationContext是一个接口,依赖于子类的具体实现)
  2. 不属于ConfigurableApplicationContext的所有子类对象

好,了解了这点,我们才能更好的明白为什么要这么判断,那么那些工厂类不是ConfigurableApplicationContext的子类呢,注意这里说的是工厂类,那么我们就要了解Spring一共存在多少个工厂类实现,所以如何找到所有的工厂类呢?我们会发现Spring框架的设计都是从接口开始的,在Java一类面向对象的语言中,源码和代码的设计都有一个规律,就是一切源码从接口开始,这话说的有些绝对,但是至少大部分是,所以我们现在找的是BeanFactory接口,并找到其所有的实现,如图所示:

在这里插入图片描述

看了这张图我们会发现,BeanFactory接口下来和ConfigurableApplicationContext接口同级的并且没有继承ConfigurableApplicationContext有以下几个:

  1. ConfigurableListableBeanFactory
  2. AbstractBeanFactory

继续往下看,你会发现这两个类自成一派,和另一边毫无关系,并且最终都是指向了DefaultListableBeanFactory 这个类,那么这样就很清晰了,存在两种情况:

  1. ConfigurableApplicationContext及其子类
  2. DefaultListableBeanFactory 工厂类

在这里插入图片描述

那么再提出一个问题,为什么需要DefaultListableBeanFactory这个工厂类,不能用ConfigurableApplicationContext直接创建工厂么,这个问题我们再开一章,因为必须要解析清楚ConfigurableApplicationContext和DefaultListableBeanFactory这两个类的不同作用,预计东西可能有点儿多

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值