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源码加载bean定义信息 loadBeanDefinitions -> 正文阅读

[Java知识库]spring源码加载bean定义信息 loadBeanDefinitions

上编文章咱们已经把工厂容器准备好了,那么既然是容器就会存放数据,它是怎么存放的呢?
上一篇传送门
咱们先看下bean定义信息的类关系
在这里插入图片描述

loadBeanDefinitions 目前咱们先看 普通 bean定义信息加载

这个方法调用比较深,过渡流程

  1. AbstractXmlApplicationContext.loadBeanDefinitions 创建bean定义信息的读取器
  2. AbstractXmlApplicationContext.loadBeanDefinitions(beanDefinitionReader)使用读取器进行加载bean的定义信息
  3. AbstractBeanDefinitionReader.loadBeanDefinitions 循环多个*.xml文件,进行加载
  4. AbstractBeanDefinitionReader.loadBeanDefinitions(location,)解析location,获取resources
  5. AbstractBeanDefinitionReader.loadBeanDefinitions(resources) 批量处理resources
  6. AbstractBeanDefinitionReader.loadBeanDefinitions(resource) 循环多个资源调用单个资源加载
  7. XmlBeanDefinitionReader.loadBeanDefinitions(EncodedResource) 读取文件流,进行加载
  8. XmlBeanDefinitionReader.doLoadBeanDefinitions(inputSource, encodedResource.getResource()) 把文件流解析成Document
  9. XmlBeanDefinitionReader.registerBeanDefinitions,创建文档读取器
  10. DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(doc,XmlReaderContext) 使用默认的bean定义信息文档读取器来注册bean定义信息
  11. DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(element)
  12. DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(element,delegate)真正开始解析xml标签了

DefaultBeanDefinitionDocumentReader.parseBeanDefinitions 解析xml文档

遍历xml文档中的节点,并进行解析
咱们这里先看普通的bean标签是如何解析成bean定义信息的,定制化在AOP时候再看是怎么执行的。

<bean id="myProperties" class="com.msgqu.debug.config.MyProperties">
	<property name="url" value="${msgqu.name}"></property>
</bean>
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				// 如果是 http://www.springframework.org/schema/beans ,那么则是默认的解析标签
				if (delegate.isDefaultNamespace(ele)) {
					parseDefaultElement(ele, delegate);
				}else {
					// 解析定制化标签
					delegate.parseCustomElement(ele);
				}
			}
		}
	}else {
		// 解析定制化标签
		delegate.parseCustomElement(root);
	}
}

DefaultBeanDefinitionDocumentReader.parseDefaultElement(ele, delegate) 解析默认标签

开始解析标签

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		//解析bean标签
		processBeanDefinition(ele, delegate);
	}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		doRegisterBeanDefinitions(ele);
	}
}

DefaultBeanDefinitionDocumentReader.processBeanDefinition 开始解析bean标签

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	//解析bean定义信息元素,并包装成BeanDefinitionHolder
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// Register the final decorated instance.
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
		}catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);
		}
		
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

BeanDefinitionParserDelegate.parseBeanDefinitionElement(ele) 使用策略解析类对bean标签进行解析

BeanDefinitionParserDelegate是bean标签的解析类

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
	//获取到id属性
	String id = ele.getAttribute(ID_ATTRIBUTE);
	// name属性是全限定类名,方便后面实例化的时候使用,也会用于判断这个对象是否是class
	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
	//注册别名,咱们知道,一个bean对象可以有多个别名
	List<String> aliases = new ArrayList<>();
	if (StringUtils.hasLength(nameAttr)) {
		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
		aliases.addAll(Arrays.asList(nameArr));
	}
	String beanName = id;
	if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
		beanName = aliases.remove(0);
	}
	//检查bean的名称是必须的
	if (containingBean == null) {
		checkNameUniqueness(beanName, aliases, ele);
	}
	//创建beanDefinition,解析bean标签中的属性,并赋值给BeanDefinition
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		//这里可以扩展bean名称生成器,有兴趣的可以了解哈
		if (!StringUtils.hasText(beanName)) {
			try {
				if (containingBean != null) {
					beanName = BeanDefinitionReaderUtils.generateBeanName(
							beanDefinition, this.readerContext.getRegistry(), true);
				}
				else {
					beanName = this.readerContext.generateBeanName(beanDefinition);
					String beanClassName = beanDefinition.getBeanClassName();
					if (beanClassName != null &&
							beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
							!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
						aliases.add(beanClassName);
					}
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Neither XML 'id' nor 'name' specified - " +
							"using generated bean name [" + beanName + "]");
				}
			}
			catch (Exception ex) {
				error(ex.getMessage(), ele);
				return null;
			}
		}
		String[] aliasesArray = StringUtils.toStringArray(aliases);
		// 返回bean定义信息的包装者
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}
	return null;
}
BeanDefinitionParserDelegate.parseBeanDefinitionElement 根据bean标签创建出bean定义信息

这里创建出的bean定义信息是GenericBeanDefinition

public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
	//包装bean名称,放置到ArrayDeque中 类似标识递归中操作的过程一样 ,方便在解析过程中获取对应标签。
	this.parseState.push(new BeanEntry(beanName));
	//从bean标签中获取class 和 parent 属性值
	String className = null;
	if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
		className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
	}
	String parent = null;
	if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
		parent = ele.getAttribute(PARENT_ATTRIBUTE);
	}

	try {
		//创建bean定义信息
		AbstractBeanDefinition bd = createBeanDefinition(className, parent);
		//解析bean的其他属性 singleton、scope、abstract、lazy-init、autowire、autowire-candidate、primary、factory-method、factory-bean
		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
		//解析子标签
		parseMetaElements(ele, bd);
		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
		//方法替换
		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
		//解析构造,为了方便实例化
		parseConstructorArgElements(ele, bd);
		//解析Property属性
		parsePropertyElements(ele, bd);
		parseQualifierElements(ele, bd);
		bd.setResource(this.readerContext.getResource());
		bd.setSource(extractSource(ele));
		//返回GenericBeanDefinition
		return bd;
	}catch (ClassNotFoundException ex) {
		error("Bean class [" + className + "] not found", ele, ex);
	}catch (NoClassDefFoundError err) {
		error("Class that bean class [" + className + "] depends on not found", ele, err);
	}catch (Throwable ex) {
		error("Unexpected failure during bean definition parsing", ele, ex);
	}finally {
		this.parseState.pop();
	}
	return null;
}
BeanDefinitionParserDelegate.parsePropertyElement 解析bean标签中的 标签
public void parsePropertyElement(Element ele, BeanDefinition bd) {
	String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
	if (!StringUtils.hasLength(propertyName)) {
		error("Tag 'property' must have a 'name' attribute", ele);
		return;
	}
	this.parseState.push(new PropertyEntry(propertyName));
	try {
		if (bd.getPropertyValues().contains(propertyName)) {
			error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
			return;
		}
		//解析Property的value值
		Object val = parsePropertyValue(ele, bd, propertyName);
		PropertyValue pv = new PropertyValue(propertyName, val);
		parseMetaElements(ele, pv);
		pv.setSource(extractSource(ele));
		bd.getPropertyValues().addPropertyValue(pv);
	}
	finally {
		this.parseState.pop();
	}
}
BeanDefinitionParserDelegate.parsePropertyValue 解析
public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
	String elementName = (propertyName != null ?
			"<property> element for property '" + propertyName + "'" :
			"<constructor-arg> element");
	// Should only have one child element: ref, value, list, etc.
	NodeList nl = ele.getChildNodes();
	Element subElement = null;
	for (int i = 0; i < nl.getLength(); i++) {
		Node node = nl.item(i);
		if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
				!nodeNameEquals(node, META_ELEMENT)) {
			if (subElement != null) {
				error(elementName + " must not contain more than one sub-element", ele);
			}else {
				subElement = (Element) node;
			}
		}
	}
	//得到 ref 和 value 的值是否存在
	boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
	boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
	if ((hasRefAttribute && hasValueAttribute) ||
			((hasRefAttribute || hasValueAttribute) && subElement != null)) {
		error(elementName +
				" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
	}

	if (hasRefAttribute) {
		//如果是引用类型 ,进行包装成运行时bean引用 <property name="field" ref="beanName"></property>
		String refName = ele.getAttribute(REF_ATTRIBUTE);
		if (!StringUtils.hasText(refName)) {
			error(elementName + " contains empty 'ref' attribute", ele);
		}
		RuntimeBeanReference ref = new RuntimeBeanReference(refName);
		ref.setSource(extractSource(ele));
		return ref;
	}else if (hasValueAttribute) {
		//创建value值包装 (value值,及类型)<property name="url" value="${com.xxx}"/>
		TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
		valueHolder.setSource(extractSource(ele));
		return valueHolder;
	}else if (subElement != null) {
		return parsePropertySubElement(subElement, bd);
	}else {
		// Neither child element nor "ref" or "value" attribute found.
		error(elementName + " must specify a ref or value", ele);
		return null;
	}
}

现在咱们已经获取到了BeanDefinition咱们再回到parseBeanDefinitionElement方法中

BeanDefinitionReaderUtils.registerBeanDefinition 注册bean的定义信息

看注册之前,咱们试想下,bean的定义信息会注册到哪里呢?

public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {
	String beanName = definitionHolder.getBeanName();
	//注册bean定义信息   registry:DefaultListableBeanFactory
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
	// 这里设计的还是比较巧妙,Map中 key是别名,value是beanName
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}

DefaultListableBeanFactory.registerBeanDefinition 注册bean定义信息

注册之前咱们试想下,如果是自己的来存储的话,会使用什么样的数据结构?

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		//如果缓存中存在bean定义信息,那么要求是必要支持bean定义信息的覆盖
		//在这属性是在咱们创建完容器的时候设置的定制化属性,想不起来可以看下
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		//把解析出的bean定义信息注册到Map中
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}else {
		if (hasBeanCreationStarted()) {
			//如果已经创建
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				removeManualSingletonName(beanName);
			}
		}else {
			// 注册到beanDefinitionMap中
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}
	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}else if (isConfigurationFrozen()) {
		clearByTypeCache();
	}
}

单个bean标签也注册完了,咱们梳理下流程

bean定义信息是为了创建bean对象的时候使用,除了特殊情况(FactoryBean等),基本上都会先创建bean定义信息,所以这块是比较周要的一环

  1. 加载配置文件locations
  2. 创建xml解析器
  3. 解析标签,并生成bean定义信息
  4. 解析标签内的属性
  5. 注册bean定义信息
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:14:58  更:2022-03-08 22:18:29 
 
开发: 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/24 10:25:45-

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