BeanDefinition解析

101 阅读4分钟

BeanDefinition的解析就是将对bean的定义转换为spring内部的数据结构

准备两个类和spring的xml文件 UserService.java ` public class UserService {

private UserDto userDto;

private Map<String,String> map;

public UserDto getUserDto() {
	return userDto;
}

public void setUserDto(UserDto userDto) {
	this.userDto = userDto;
}

public Map<String, String> getMap() {
	return map;
}

public void setMap(Map<String, String> map) {
	this.map = map;
}

} `

UserDto.java ` public class UserDto { String name; int age;

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public int getAge() {
	return age;
}

public void setAge(int age) {
	this.age = age;
}

public void initMethod(){
	System.out.println("initMethod start--------------");

}

} `

spring的配置文件bean.xml `

<bean id="userService" class="service.UserService">
	<property name="map">
		<map>
			<entry key="name" value="test"/>
			<entry key="age" value="20"/>
		</map>
	</property>
	<property name="userDto" ref="userDto"></property>
</bean>

<!--创建bean-->
<bean id="userDto" class="dto.UserDto" init-method="initMethod" name="dto" lazy-init="true">
	<property name="age" value="20"/>
	<property name="name" value="保质期已过"/>
</bean>

`

main方法测试

` public static void main(String[] args) {

    //1.资源定位
Resource resource = new ClassPathResource("bean.xml");
//2.创建IOC容器,这里使用DefaultListableBeanFactory作为IOC容器
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
//3.读取BeanDefinition并注册到IOC容器中
BeanDefinitionReader reader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
reader.loadBeanDefinitions(resource);
    

} `

具体的过程是由BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader.registerBeanDefinitions方法实现

DefaultBeanDefinitionDocumentReader.java `public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {

	this.readerContext = readerContext;
	logger.debug("Loading bean definitions");
	Element root = doc.getDocumentElement();//root代表根节点<beans>
	doRegisterBeanDefinitions(root);
            

}`

在doRegisterBeanDefinitions会调用parseBeanDefinitions方法,在parseBeanDefinitions中会调用parseDefaultElement方法

`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)) {
		// recurse
		doRegisterBeanDefinitions(ele);
	}
            
}`
    

具体的解析过程会委托给BeanDefinitionParseDelegate.parseBeanDefinitionElement完成,这个类包含对bean规则定义的解析,比如bean属性(id,name,init-method等)的设定,property的设置

`protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {

	//处理给定的bean定义——》BeanDefinition
	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);
		}
		// Send registration event.
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
            
}`

parseBeanDefinitionElement方法

`public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {

	//获取bean的id,name属性
	String id = ele.getAttribute(ID_ATTRIBUTE);
	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

	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.isDebugEnabled()) {
			logger.debug("No XML 'id' specified - using '" + beanName +
					"' as bean name and " + aliases + " as aliases");
		}
	}
	//检查beanName是否存在
	if (containingBean == null) {
		checkNameUniqueness(beanName, aliases, ele);
	}
	//对Bean元素的详细解析
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		if (!StringUtils.hasText(beanName)) {
			try {
				if (containingBean != null) {
					beanName = BeanDefinitionReaderUtils.generateBeanName(
							beanDefinition, this.readerContext.getRegistry(), true);
				}
				else {
					beanName = this.readerContext.generateBeanName(beanDefinition);
					// Register an alias for the plain bean class name, if still possible,
					// if the generator returned the class name plus a suffix.
					// This is expected for Spring 1.2/2.0 backwards compatibility.
					String beanClassName = beanDefinition.getBeanClassName();
					if (beanClassName != null &&
							beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
							!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
						aliases.add(beanClassName);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("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);
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}

	return null;
            
}`
    

parseBeanDefinitionElement 方法

`public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) {

	this.parseState.push(new BeanEntry(beanName));

	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 {
		//创建BeanDefinition,为bean定义信息的载入做准备
		AbstractBeanDefinition bd = createBeanDefinition(className, parent);
		//解析bean的属性
		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
		//解析bean的元素
		parseMetaElements(ele, bd);
		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
		//解析bean的构造函数
		parseConstructorArgElements(ele, bd);
		//解析property
		parsePropertyElements(ele, bd);
		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;
            
}`
    

parseBeanDefinitionAttributes方法,完成对bean属性的解析,比如init-method,lazy-init等,如果没有设置属性会设置默认值

`public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

	if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
		error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
	}
	//设置scope
	else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
		bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
	}
	else if (containingBean != null) {
		// Take default from containing bean in case of an inner bean definition.
		bd.setScope(containingBean.getScope());
	}

	if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
		bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
	}
	//设置懒加载
	String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
	if (isDefaultValue(lazyInit)) {
		lazyInit = this.defaults.getLazyInit();
	}
	bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
	//设置自动注入
	String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
	bd.setAutowireMode(getAutowireMode(autowire));

	if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
		String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
		bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
	}

	String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
	if (isDefaultValue(autowireCandidate)) {
		String candidatePattern = this.defaults.getAutowireCandidates();
		if (candidatePattern != null) {
			String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
			bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
		}
	}
	else {
		bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
	}

	if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
		bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
	}
	//设置初始化方法
	if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
		String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
		bd.setInitMethodName(initMethodName);
	}
	else if (this.defaults.getInitMethod() != null) {
		bd.setInitMethodName(this.defaults.getInitMethod());
		bd.setEnforceInitMethod(false);
	}
	//设置销毁方法
	if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
		String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
		bd.setDestroyMethodName(destroyMethodName);
	}
	else if (this.defaults.getDestroyMethod() != null) {
		bd.setDestroyMethodName(this.defaults.getDestroyMethod());
		bd.setEnforceDestroyMethod(false);
	}

	if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
		bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
	}
	if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
		bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
	}

	return bd;
            
}`
    

parsePropertyElements完成对property的解析,获取元素后判断是否是elment,如果是的会调用parsePropertyElement进行元素和属性的解析,生成PropertyValue对象,将PropertyValue对象放入集合中,最后添加到BeanDefinition中

`public void parsePropertyElements(Element beanEle, BeanDefinition bd) {

	NodeList nl = beanEle.getChildNodes();
	for (int i = 0; i < nl.getLength(); i++) {
		Node node = nl.item(i);
		if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
			parsePropertyElement((Element) node, bd);
		}
	}
            
}`
    

parsePropertyElement解析Property节点

`public void parsePropertyElement(Element ele, BeanDefinition bd) {

	//获取属性name的值,比如<property name="age" value="20"/> 获取到的就是“age”
	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;
		}
		//对元素value值的解析,ref,value,子元素
		Object val = parsePropertyValue(ele, bd, propertyName);
		//创建PropertyValue对象
		PropertyValue pv = new PropertyValue(propertyName, val);
		parseMetaElements(ele, pv);
		pv.setSource(extractSource(ele));
		//将PropertyValue对象放入集合中
		bd.getPropertyValues().addPropertyValue(pv);
	}
	finally {
		this.parseState.pop();
	}
            
}`
    

parsePropertyValue对value,ref,elment的解析

`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)) {
			// Child element is what we're looking for.
			//Property中含有子元素
			if (subElement != null) {
				error(elementName + " must not contain more than one sub-element", ele);
			}
			else {
				subElement = (Element) node;
			}
		}
	}
	//ref属性
	boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
	//value属性
	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);
	}
	//如果是ref属性,返回RuntimeBeanReference对象
	if (hasRefAttribute) {
		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;
	}
	//如果是value属性,返回TypedStringValue
	else if (hasValueAttribute) {
		TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
		valueHolder.setSource(extractSource(ele));
		return valueHolder;
	}
	//如果还有子元素,则继续解析子元素,里面包含map,set,list的解析
	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;
	}
            
}`
    

parsePropertySubElement判断节点名称,这里以map集合为例,判断如果是map节点则调用parseMapElement,解析entry节点的属性key和value的值,将值放到新的map中并返回

`public Map<Object, Object> parseMapElement(Element mapEle, @Nullable BeanDefinition bd) { String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE); String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);

	List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);
	ManagedMap<Object, Object> map = new ManagedMap<>(entryEles.size());
	map.setSource(extractSource(mapEle));
	map.setKeyTypeName(defaultKeyType);
	map.setValueTypeName(defaultValueType);
	map.setMergeEnabled(parseMergeAttribute(mapEle));

	for (Element entryEle : entryEles) {
		// Should only have one value child element: ref, value, list, etc.
		// Optionally, there might be a key child element.
		NodeList entrySubNodes = entryEle.getChildNodes();
		Element keyEle = null;
		Element valueEle = null;
		for (int j = 0; j < entrySubNodes.getLength(); j++) {
			Node node = entrySubNodes.item(j);
			if (node instanceof Element) {
				Element candidateEle = (Element) node;
				if (nodeNameEquals(candidateEle, KEY_ELEMENT)) {
					if (keyEle != null) {
						error("<entry> element is only allowed to contain one <key> sub-element", entryEle);
					}
					else {
						keyEle = candidateEle;
					}
				}
				else {
					// Child element is what we're looking for.
					if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) {
						// the element is a <description> -> ignore it
					}
					else if (valueEle != null) {
						error("<entry> element must not contain more than one value sub-element", entryEle);
					}
					else {
						valueEle = candidateEle;
					}
				}
			}
		}

		// Extract key from attribute or sub-element.
		Object key = null;
		boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE);
		boolean hasKeyRefAttribute = entryEle.hasAttribute(KEY_REF_ATTRIBUTE);
		if ((hasKeyAttribute && hasKeyRefAttribute) ||
				(hasKeyAttribute || hasKeyRefAttribute) && keyEle != null) {
			error("<entry> element is only allowed to contain either " +
					"a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle);
		}
		if (hasKeyAttribute) {
			key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle);
		}
		else if (hasKeyRefAttribute) {
			String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error("<entry> element contains empty 'key-ref' attribute", entryEle);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(entryEle));
			key = ref;
		}
		else if (keyEle != null) {
			key = parseKeyElement(keyEle, bd, defaultKeyType);
		}
		else {
			error("<entry> element must specify a key", entryEle);
		}

		// Extract value from attribute or sub-element.
		Object value = null;
		boolean hasValueAttribute = entryEle.hasAttribute(VALUE_ATTRIBUTE);
		boolean hasValueRefAttribute = entryEle.hasAttribute(VALUE_REF_ATTRIBUTE);
		boolean hasValueTypeAttribute = entryEle.hasAttribute(VALUE_TYPE_ATTRIBUTE);
		if ((hasValueAttribute && hasValueRefAttribute) ||
				(hasValueAttribute || hasValueRefAttribute) && valueEle != null) {
			error("<entry> element is only allowed to contain either " +
					"'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
		}
		if ((hasValueTypeAttribute && hasValueRefAttribute) ||
			(hasValueTypeAttribute && !hasValueAttribute) ||
				(hasValueTypeAttribute && valueEle != null)) {
			error("<entry> element is only allowed to contain a 'value-type' " +
					"attribute when it has a 'value' attribute", entryEle);
		}
		if (hasValueAttribute) {
			String valueType = entryEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
			if (!StringUtils.hasText(valueType)) {
				valueType = defaultValueType;
			}
			value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), valueType, entryEle);
		}
		else if (hasValueRefAttribute) {
			String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error("<entry> element contains empty 'value-ref' attribute", entryEle);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(entryEle));
			value = ref;
		}
		else if (valueEle != null) {
			value = parsePropertySubElement(valueEle, bd, defaultValueType);
		}
		else {
			error("<entry> element must specify a value", entryEle);
		}

		// Add final key and value to the Map.
		map.put(key, value);
	}

	return map;
}`