Spring源码解析-refresh(二)-obtainFreshBeanFactory方法

本文介绍了如何在Spring框架中子类化ApplicationContext,通过override `refreshBeanFactory()`方法,关闭旧的BeanFactory,重新加载XML配置,定制bean工厂属性,最终解析并注入BeanDefinition。
部署运行你感兴趣的模型镜像

总结一句话: 告诉子类刷新内部bean工厂,读取xml文件,并解析出来,注入到beanfactory里面去。

进入到obtainFreshBeanFactory可看到有两个方法:

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

我们先研究refreshBeanFactory()方法:

/**

此实现执行此上下文的底层 bean 工厂的实际刷新,关闭先前的 bean 工厂(如果有)并为上下文生命周期的下一个阶段初始化一个新的 bean 工厂。
*/
@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) { //如果存在了beanfactory,则关闭掉,
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
            //为了序列号指定id,可以从id防序列号化到beanFactory对象
             //id的值是在super()方法中进行设值的,这里只是单纯的获取id ,详细见                
             https://blog.youkuaiyun.com/u012249177/article/details/81008334?spm=1001.2014.3001.5501 			
             beanFactory.setSerializationId(getId());  
            //定制beanfactory,设置相关属性,包括是否允许覆盖同名陈的不同定义的对象以及循环依赖
			customizeBeanFactory(beanFactory);
            //初始化documentReader,并进行xml文件解读及解析
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

然后到 里面重点的类:  customizeBeanFactory定制化beanfactory

自定义此上下文使用的内部 bean 工厂。 每次refresh()尝试时调用。
如果指定,默认实现应用此上下文的“allowBeanDefinitionOverriding”和“allowCircularReferences”设置。 可以在子类中覆盖以自定义DefaultListableBeanFactory的任何设置。
参数:
beanFactory – 为此上下文新创建的 bean 工厂
也可以看看:
DefaultListableBeanFactory.setAllowBeanDefinitionOverriding , DefaultListableBeanFactory.setAllowCircularReferences , DefaultListableBeanFactory.setAllowRawInjectionDespiteWrapping , DefaultListableBeanFactory.setAllowEagerClassLoading

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
     //如果属性allowBeanDefinitionOverriding 不为空,则设置给beanfactory对象相应属性,是否允许覆盖同名称的不同定义的对象。    
		if (this.allowBeanDefinitionOverriding != null) {
	 //如果属性allowBeanDefinitionOverriding不为空,则设置给beanfactory对象相应属性,是否bean存在循环依赖		beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

例如我们使用重写父类的方法:

    @Override
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        super.setAllowBeanDefinitionOverriding(false);
        super.setAllowCircularReferences(false); 
        //super.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
        super.customizeBeanFactory(beanFactory);
    }

然后看下代码执行顺序, 先子类设置这两个属性为false,然后再父类的方:

然后执行到父类的方法:

我们到了最后的一个方法:loadBeanDefinitions

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		// 以Resource的方式获得配置文件的资源位置
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		// 以String的形式获得配置文件的位置 ,此处在外面进行了setconfigLoaction的设置,此处为单纯的获取
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

loadBeanDefinitions: 

// 此处获取xml文件的document对象,这个解析过程是由documentLoader完成的,从String[] -string-Resource[]- resource,最终开始将resource读取成一个document文档,根据文档的节点信息封装成一个个的BeanDefinition对象
			Document doc = doLoadDocument(inputSource, resource);
            //这里是解析document,并将解析后的参数放到beanfacotory中
            int count = registerBeanDefinitions(doc, resource);

解析的最终代码:

 

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// beanDefinitionHolder是beanDefinition对象的封装类,封装了BeanDefinition,bean的名字和别名,用它来完成向IOC容器的注册
		// 得到这个beanDefinitionHolder就意味着beandefinition是通过BeanDefinitionParserDelegate对xml元素的信息按照spring的bean规则进行
		// 解析得到的
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 向ioc容器注册解析得到的beandefinition的地方
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			// 在beandefinition向ioc容器注册完成之后,发送消息
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

 

		// Still in startup registration phase
				// 注册beanDefinition
				this.beanDefinitionMap.put(beanName, beanDefinition);
				// 记录beanName
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);

 

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

Llama Factory

Llama Factory

模型微调
LLama-Factory

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值