IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring源码解析-refresh(二)-obtainFreshBeanFactory方法 -> 正文阅读

[Java知识库]Spring源码解析-refresh(二)-obtainFreshBeanFactory方法

总结一句话:?告诉子类刷新内部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.csdn.net/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);

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:08:16  更:2021-09-13 09:10:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:44:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码