Spring中的之启动过程obtainFreshBeanFactory详解

 更新时间:2024年02月14日 08:27:45   作者:thewindkee  
这篇文章主要介绍了Spring中的之启动过程obtainFreshBeanFactory详解,在refresh时,prepareRefresh后,马上就调用了obtainFreshBeanFactory创建beanFactory以及扫描bean信息(beanDefinition),并通过BeanDefinitionRegistry注册到容器中,需要的朋友可以参考下

1.refresh流程

refresh是spring启动的关键方法,refresh启动过程中,先要得到beanFactory 以及 需要交给beanFactory管理的bean。

在refresh时,prepareRefresh后,马上就调用了obtainFreshBeanFactory创建beanFactory以及扫描bean信息(beanDefinition),并通过BeanDefinitionRegistry注册到容器中。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		//后面省略
		....
		}
	}

2.obtainFreshBeanFactory扫描bean定义信息并注册

这里以通过XML配置spring来举例。

  1. 创建DefaultListableBeanFactory,设置是否支持beanDefinition重写以及是否支持循环引用。
  2. 载入beanDefinition
    • 得到所有spring相关的xml,将其转为Document对象。
    • 解析Document,判断node是否属于beans(http://www.springframework.org/schema/beans)这个命名空间(Namespace)。针对默认命名空间(beans)和非默认空间,有不同的处理。
      • 处理默认命名空间相关node:import,alias,bean,beans4种node。
      • 处理非默认命名空间相关node,如:<context:annotation-config/>、<context:component-scan base-package="xx"/>、<mongo:mongo-client/>
      • 注册beanDefinition

obtainFreshBeanFactory重要流程

在这里插入图片描述

3.必须了解的类

3.1 beanDefinition

包含欲交给spring管理的bean信息 扫描了一个对象的信息,包括class,property等。

3.2 NamespaceHandler

注册自定义解析类 该接口的作用:注册可解析xml中自定义的标签Parser。 实现类类名与命名空间名字对应。

常见的NamespaceHandler实例:ContextNamespaceHandler 很明显能看出有常用的 <context:annotation-config/>、<context:component-scan base-package="xx"/>、<context:property-placeholder/>对应的解析类。

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
	@Override
	public void init() {
		registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
		registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
		registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
		registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
	}
}

3.3 BeanDefinitionParser接口

配合DefaultBeanDefinitionDocumentReader去解析xml中自定义的标签。 接口需要实现BeanDefinition parse(Element element, ParserContext parserContext);方法,该方法返回一个beanDefination。但是实际都没有处理这个返回值, 在parse内部就解析beanDefination并注册到beanDefinationMap中了。 实现类与节点名称对应。

3.4 BeanDefinitionParser与ContextNamespaceHandler的关系

类似于 xHandler.put(“a”,parserA); Handler.put(“b”,parserB); 当处理非默认命名空间的节点时,如x命名空间中的<a>节点,使用xHandler.get(“a”).parse来解析并注册beanDefinition

4.处理默认命名空间

以处理<bean>为例,调用装饰器去解析delegate.parseBeanDefinitionElement(ele)将bean上的属性,如id,name,property,class等,并返回一个BeanDefinition对象。然后调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())将其注册到beanDefinitionMap中。

5.处理非默认命名空间

根据命名空间得到对应的NamespaceHandler,然后调用节点对应的parser去解析注册beanDefinition.

如context命名空间中解析<context:component-scan base-package="com.gkwind.xxx"/>的ComponentScanBeanDefinitionParser

这里解析有点复杂,但思路很简单: 从xml文件对应的element中处理对应的node。将node的属性装配成beanDefinition或者利用其属性代表的特殊含义去注册beanDefinition. 如这里<context:component-scan base-package="com.gkwind.xxx"/>),就表明需要:

1.扫描这个包下面的所有class。

2.将符合filter的class包装为beanDefinition并注册到beanDefinitionMap中。

如:含有@Component等注解的class

在这里插入图片描述

6.debug的时候遇到的问题

DefaultNamespaceHandlerResolver的toString方法会触发getHandlerMappings,而使用idea debug的时候会调用toString引起handlerMapping初始化,导致看到handlerMapping莫名的出现值。

	@Override
	public String toString() {
		return "NamespaceHandlerResolver using mappings " + getHandlerMappings();
	}

7.整体流程

在这里插入图片描述

8.其他

注册beanDefinition需要关注org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition,它会将beanDefinition加入beanDefinitionMap中。

到此这篇关于Spring中的之启动过程obtainFreshBeanFactory详解的文章就介绍到这了,更多相关Spring的obtainFreshBeanFactory内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JDBC连接SQL Server数据库实现增删改查的全过程

    JDBC连接SQL Server数据库实现增删改查的全过程

    实际开发中手动的输入SQL语句是少之又少,大多数情况下是通过编译代码进行来控制自动执行,下面这篇文章主要给大家介绍了关于JDBC连接SQL Server数据库实现增删改查的相关资料,需要的朋友可以参考下
    2023-04-04
  • 详解Java反射创建对象

    详解Java反射创建对象

    今天带大家学习Java的基础知识,文中对Java反射创建对象作了非常详细的介绍及代码示例,对正在学习Java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • 在Java下利用log4j记录日志的方法

    在Java下利用log4j记录日志的方法

    本文先对log4j进行了简短的介绍,而后通过安装、配置和普通项目和web项目几个方面来详细介绍了在Java下利用log4j记录日志的方法,有需要的朋友们可以参考借鉴。
    2016-09-09
  • 详解static 和 final 和 static final区别

    详解static 和 final 和 static final区别

    这篇文章主要介绍了static 和 final 和 static final区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Spring七大组件是哪些以及作用

    Spring七大组件是哪些以及作用

    这篇文章主要介绍了Spring七大组件是哪些以及作用,帮助刚接触spring的朋友更快理解,如果有说的不对的地方还请指正,需要的朋友可以参考下
    2023-03-03
  • Dubbo+zookeeper搭配分布式服务的过程详解

    Dubbo+zookeeper搭配分布式服务的过程详解

    Dubbo作为分布式架构比较后的框架,同时也是比较容易入手的框架,适合作为分布式的入手框架,下面是简单的搭建过程,对Dubbo+zookeeper分布式服务搭建过程感兴趣的朋友一起看看吧
    2022-04-04
  • ssm框架Springmvc文件上传实现代码详解

    ssm框架Springmvc文件上传实现代码详解

    这篇文章主要介绍了ssm框架Springmvc文件上传实现代码详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • SpringBoot处理form-data表单接收对象数组的方法

    SpringBoot处理form-data表单接收对象数组的方法

    form-data则是一种更加灵活的编码方式,它可以处理二进制数据(如图片、文件等)以及文本数据,这篇文章主要介绍了SpringBoot处理form-data表单接收对象数组,需要的朋友可以参考下
    2023-11-11
  • 使用Mybatis遇到的坑之Integer类型参数的解读

    使用Mybatis遇到的坑之Integer类型参数的解读

    这篇文章主要介绍了使用Mybatis遇到的坑之Integer类型参数的解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • SpringBoot 配置 okhttp3的操作

    SpringBoot 配置 okhttp3的操作

    这篇文章主要介绍了SpringBoot 配置 okhttp3的操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02

最新评论