2021年3月16日星期二

Srping源码之XMLBeanFactory

​ 本文是针对Srping的

GitHub: https://github.com/lantaoGitHub/spring-framework.git

  • 首先我们从
package org.springframework.lantao;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.
@Deprecated@SuppressWarnings({"serial", "all"})public class 
  • 我们直接看loadBeanDefinition方法,源码:
/** * Load bean definitions from the specified 

上述源码可能看着比较长,但实际上这里并不是真正解析的地方,在这里做了如下:

1:从encodedResource已经封装的Resource获取InputStream;

2:如果encodedResource 中的 Encoding 不是 null 则同步设置 InputSource的 Encoding;

3:将解析动作委托给doLoadBeanDefinitions实现;

  • 接下来我们继续看doLoadBeanDefinitions方法内容:
/** * Actually load bean definitions from the specified 

当我们看着这个方法的时候,依旧不是真正的解析或注册的方法,在这里只是做了Document的加载,并将后续工作委托给了registerBeanDefinitions,registerBeanDefinitions方法的返回时注册Bean的个数;

  • 我们继续看registerBeanDefinitions的源码:
/** * Register the bean definitions contained in the given DOM document. * Called by {@code loadBeanDefinitions}. * <p>Creates a new instance of the parser class and invokes * {@code registerBeanDefinitions} on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {	//实例化 BeanDefinitionDocumentReader	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();	//获取之前的beanDefinition加载个数	int countBefore = getRegistry().getBeanDefinitionCount();	//加载

在registerBeanDefinitions方法具体实现:

1:通过BeanUtils.instantiateClass(this.documentReaderClass)的方法实例化BeanDefinitionDocumentReader;

2:通过DefaultListAbleBeanFactory中的beanDefinitionMap.size()获取之前注册bean的个数,(beanDefinitionMap是存储最终的

3:将解析

4:记录本次加载个数并返回;

  • 继续看BeanDefinitionDocumentReader的registerBeanDefinitions方法:
/** * This implementation parses bean definitions according to the "spring-beans" XSD * (or DTD, historically). * <p>Opens a DOM Document; then initializes the default settings * specified at the {@code <beans/>} level; then parses the contained bean definitions. */@Overridepublic void registerBeanDefinitions(Document doc, 
  • registerBeanDefinitions并没有做什么,我们继续看doRegisterBeanDefinitions方法:
/** * Register each bean definition within the given root {@code <beans/>} element. */@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)protected void doRegisterBeanDefinitions(Element root) {	// Any nested <beans> elements will cause recursion in this method. In	// order to propagate and preserve <beans> default-* attributes correctly,	// keep track of the current (parent) delegate, which may be null. Create	// the new (child) delegate with a reference to the parent for fallback purposes,	// then ultimately reset this.delegate back to its original (parent) reference.	// this behavior emulates a stack of delegates without actually necessitating one.	BeanDefinitionParserDelegate parent = this.delegate;	this.delegate = createDelegate(getReaderContext(), root, parent);	//验证

在doRegisterBeanDefinitions方法中验证

  • parseBeanDefinitions方法的源码:
/** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {	//验证

parseBeanDefinitions方法中已经开始对标签进行解析,区分默认标签和自定义标签,我们本次只对默认标签的源码进行解析,自定义标签自行DeBug,

  • parseDefaultElement方法的源码:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {	//解析import标签	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {		importBeanDefinitionResource(ele);	}	//解析alias标签并注册	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {		processAliasRegistration(ele);	}	//解析bean标签并注册	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {		processBeanDefinition(ele, delegate);	}	//解析beans标签	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {		// recurse		doRegisterBeanDefinitions(ele);	}}

到这里我们可以看到,spring对import/bean/alias/beans的解析过程,对于beans的解析无法就是解析beans中的bean标签,spring直接又重新调用了doRegisterBeanDefinitions方法,我们接下来进行对bean标签的解析;

  • processBeanDefinition方法:
/** * Process the given bean element, parsing the bean definition * and registering it with the registry. */protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {	//委托BeanDefinitionParserDelegate的parseBeanDefinitionElement方法进行元素解析并返回	//BeanDefinitionHolder实例,BeanDefinitionHolder已经包含了配置文件中的各种属性	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);	//当BeanDefinitionHolder返回不null的情况,若存在默认标签下的子标签再有自定义的属性,还需要再次解析	if (bdHolder != null) {		//解析默认标签中的自定义标签		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);		try {			// Register the final decorated instance.			// 进行实例注册注册操作是BeanDefinitionReaderUtisl.registerBeanDefinition进行处理			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());		}		catch (BeanDefinitionStoreException ex) {			getReaderContext().error("Failed to register bean definition with name '" +					bdHolder.getBeanName() + "'", ele, ex);		}		// Send registration event.		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));	}}

在processBeanDefinition方法中,spring做了两件事情:

1:委托BeanDefinitionParserDelegate的parseBeanDefinitionElement方法进行元素解析并返回BeanDefinitionHolder实例,BeanDefinitionHolder已经包含了配置文件中的各种属性

2:通过上获得的BeanDefinitionHolder进行bean的注册操作,通BeanDefinitionReaderUtils.registerBeanDefinition方法;

  • 通过delegate.parseBeanDefinitionElement方法进行
/** * Parses the supplied {@code <bean>} element. May return {@code null} * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. */@Nullablepublic BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {	//解析id属性	String id = ele.getAttribute(ID_ATTRIBUTE);	//解析name属性	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);	//分割name属性	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);		if (logger.isTraceEnabled()) {			logger.trace("No 

在parseBeanDefinitionElement方法中做了三件事:

1:解析id/name;

2:检查name的唯一性;

3:将信息封装到 beanDefinition中,接下来直接看parseBeanDefinitionElement方法;

  • parseBeanDefinitionElement源码:
/** * Parse the bean definition itself, without regard to name or aliases. May return * {@code null} if problems occurred during the parsing of the bean definition. */@Nullablepublic AbstractBeanDefinition parseBeanDefinitionElement(		Element ele, String beanName, @Nullable BeanDefinition containingBean) {	this.parseState.push(new BeanEntry(beanName));	String className = null;	//解析classname属性	if (ele.hasAttribute(CLASS_ATTRIBUTE)) {		className = ele.getAttribute(CLASS_ATTRIBUTE).trim();	}	String parent = null;	//解析parent属性	if (ele.hasAttribute(PARENT_ATTRIBUTE)) {		parent = ele.getAttribute(PARENT_ATTRIBUTE);	}	try {		//创建用于承载属性的AbstractBeanDefinition类型的		AbstractBeanDefinition bd = createBeanDefinition(className, parent);		//解析bean的各种属性		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);		//提取description		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));		//解析meta (元数据)		parseMetaElements(ele, bd);		//解析Lookup-method 书中53页有使用方法		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());		//解析replaced-method 书中55页有使用方法		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());		//构造函数 参数		//解析constructor-arg 书中replaced-method后边		parseConstructorArgElements(ele, bd);		//解析Property 书中replaced-method后边		parsePropertyElements(ele, bd);		//解析Qualifier 书中Property后边		parseQualifierElements(ele, bd);		bd.setResource(this.readerContext.getResource());		bd.setSource(extractSource(ele));		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;}

通过上述代码我们可以看到这里首先是实例化了一个AbstractBeanDefinition来承载各种parseBeanDefinitionAttributes方法解析了lookUp-method(方法注入),replaced-method(替换方法或方法返回值),构造函数参数constructor-argproperty属性,Qualifier属性等;上述方法的源码就不一一展示了,无非都是通过Element进行解析;

  • 接下来看真正注册的代码 BeanDefinitionReaderUtils.registerBeanDefinition
@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)		throws BeanDefinitionStoreException {	//beanName不可为空	Assert.hasText(beanName, "Bean name must not be empty");	//beanDefinition不可为空	Assert.notNull(beanDefinition, "BeanDefinition must not be null");	if (beanDefinition instanceof AbstractBeanDefinition) {		try {			//校验 MethodOverrides,MethodOverrides在解析并组装beanDefinition时有提到			((AbstractBeanDefinition) beanDefinition).validate();		}		catch (BeanDefinitionValidationException ex) {			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,						"Validation of bean definition failed", ex);		}	}	//beanDefinitionMap 存储实例的全局Map 使用ConcurrentHashMap 线程安全	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);	//如果已经注册 处理内容	if (existingDefinition != null) {		//是否覆盖		if (!isAllowBeanDefinitionOverriding()) {			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);		}		else if (existingDefinition.getRole() < beanDefinition.getRole()) {			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE			if (logger.isInfoEnabled()) {				logger.info("Overriding user-defined bean definition for bean '" + beanName +						"' with a framework-generated bean definition: replacing [" +						existingDefinition + "] with [" + beanDefinition + "]");			}		}		else if (!beanDefinition.equals(existingDefinition)) {			if (logger.isDebugEnabled()) {				logger.debug("Overriding bean definition for bean '" + beanName +						"' with a different definition: replacing [" + existingDefinition +						"] with [" + beanDefinition + "]");			}		}		else {			if (logger.isTraceEnabled()) {				logger.trace("Overriding bean definition for bean '" + beanName +						"' with an equivalent definition: replacing [" + existingDefinition +						"] with [" + beanDefinition + "]");			}		}		this.beanDefinitionMap.put(beanName, beanDefinition);	}	else {		//判断是否已经至少创建过一次 使用AbstractBeanFactory.alreadyCreated来判断		if (hasBeanCreationStarted()) {			// Cannot modify startup-time collection elements anymore (for stable iteration)			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;				if (this.manualSingletonNames.contains(beanName)) {					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);					updatedSingletons.remove(beanName);					this.manualSingletonNames = updatedSingletons;				}			}		}		else {			// 仍处于启动注册阶段			// 注册 beanDefinitionMap 新实例 beanName + beanDefinition			this.beanDefinitionMap.put(beanName, beanDefinition);			// 增加beanDefinitionNames			this.beanDefinitionNames.add(beanName);			// 清除缓存			this.manualSingletonNames.remove(beanName);		}		// 清除缓存		this.frozenBeanDefinitionNames = null;	}	if (existingDefinition != null || containsSingleton(beanName)) {		resetBeanDefinition(beanName);	}}

上述代码中首先验证了beanName和BeannDefinition不可为空,然后继续校验了MethodOverridesMethodOverrides在解析并组装beanDefinition时lookup-method和recpse-method的源码中有提到,继续判断beanDefinitionMap是否存在该bean,如果bean已经存在,通过allowBeanDefinitionOverriding属性判断是否可覆盖,反之则抛出异常;如果不存在则需要判断本次是否是第一次注册bean,如果是则初始化beanDefinitionMap后进行put操作,反之直接put beanDefinitionMap完成注册;

至此我们已经看完了整个

1615879776045-153328









原文转载:http://www.shaoqun.com/a/631651.html

跨境电商:https://www.ikjzd.com/

亚马逊t恤:https://www.ikjzd.com/w/1932

吴佳:https://www.ikjzd.com/w/1770


​ 本文是针对Srping的GitHub:https://github.com/lantaoGitHub/spring-framework.git首先我们从packageorg.springframework.lantao;importorg.springframework.beans.factory.BeanFactory;importorg.springframework.beans.fac
邓白氏集团:https://www.ikjzd.com/w/582
亚马逊应用商店:https://www.ikjzd.com/w/531
跨境通网站:https://www.ikjzd.com/w/1329
新手课堂 |让你5分钟搞懂亚马逊Listing页面!:https://www.ikjzd.com/home/18367
亚马逊卖家支持:https://www.ikjzd.com/w/806
谷歌营销:如何利用目标客户匹配工具挖掘潜在用户:https://www.ikjzd.com/home/132116

没有评论:

发表评论