Spring IOC源码:简单易懂的Spring IOC 思路介绍
Spring IOC源码:核心流程介绍
Spring IOC源码:ApplicationContext刷新前准备工作
Spring IOC源码:obtainFreshBeanFactory 详解(上)
Spring IOC源码:obtainFreshBeanFactory 详解(中)
Spring IOC源码:obtainFreshBeanFactory 详解(下)
Spring IOC源码:<context:component-scan>源码详解
Spring IOC源码:invokeBeanFactoryPostProcessors 后置处理器详解
Spring IOC源码:registerBeanPostProcessors 详解
Spring IOC源码:实例化前的准备工作
Spring IOC源码:finishBeanFactoryInitialization详解
Spring IoC源码:getBean 详解
Spring IoC源码:createBean( 上)
Spring IoC源码:createBean( 中)
Spring IoC源码:createBean( 下)
Spring IoC源码:finishRefresh 完成刷新详解
上篇文章我们介绍了prepareRefresh方法,配置解析前的准备工作,和obtainFreshBeanFactory方法,配置解析核心处理方法。我们讲解到了parseBeanDefinitions方法,该方法会根据命名空间去选择对应的逻辑处理。本章节介绍默认命名空间的处理逻辑parseDefaultElement(ele, delegate);
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;
if (delegate.isDefaultNamespace(ele)) {
//默认命名空间节点的处理,例如:
parseDefaultElement(ele, delegate);
}
else {
// 自定义命名空间节点的处理,例如: 、
delegate.parseCustomElement(ele);
}
}
}
}
else {
//非默认命名空间走其它逻辑
delegate.parseCustomElement(root);
}
}
进入parseDefaultElement(ele, delegate)方法,我们可以看到有四种类型的判断,import、alias、bean、beans。这里获取一级节点,判断节点类型选择对应的解析方法。几种类型的解析都是比较类似的,这里我们使用的bean,学会的bean去看其它都是大同小异,而beans节点其实是重新调用一遍doRegisterBeanDefinitions方法,进行子节点的遍历解析工作。bean节点解析见方法1
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);
}
}
xml配置如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="teacher" class="service.impl.Teacher">
<property name="name" value="张三">property>
<property name="age" value="30">property>
bean>
beans>
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//通过解析器进行解析,解析出类名、class、id、父类、属性依赖等
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//bean解析器只能解析一些默认的配置,这里判断是否有自定义的属性或子节点需要进一步解析并封装,
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 将bdHolder 注册到上下文缓存中beanDefinitionNames、beanDefinitionMap、aliasMap
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));
}
}
1、delegate.parseBeanDefinitionElement(ele)方法:见方法2详解
2、delegate.decorateBeanDefinitionIfRequired(ele, bdHolder)方法:
这个方法主要是考虑到bean节点中的属性或者子节点包含了自定义内容,默认的解析器没办法解析到,所以需要做下后置处理,判断是否有自定义的,通过自定义获取命名空间,通过命名空间加载解析器进行处理,将处理好的值封装到步骤1解析出来的BeanDefinitionHolder 中。例如下面的“zhudachang”属性和 < myBean > 子节点。这节我们要研究默认命名空间,所以这里不做深入,等后面讲解了自定义的内容后,再来看这块就比较简单了。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="teacher" class="service.impl.Teacher" zhudachang="">
<property name="name" value="张三">property>
<property name="age" value="30">property>
<myBean>myBean>
bean>
beans>
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取id和name属性值
String id = ele.getAttribute(ID_ATTRIBUTE);
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));
}
//如果beanName为空,则以aliases中的第一条数据作为beanName名称,并移除。
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//查询一下该beanName 名称是否作为第一个被使用了
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//解析节点并封装成GenericBeanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
//默认规则生成,获取class名称,如果class名称为空,则看beanDefinition的父类或FactoryBean的名称+固定后最作为Bean名称,如果是内部的Bean则按另一个逻辑生成;
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.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);
//将beanDefinition跟类名、别名封装成 BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
1、beanName的获取规则,如果bean节点配置了id属性,则以id作为beanName。如果没有id,但是有配置name属性,则解析名称中是否含有多个,如果有多个则将第一个作为beanName,其余的作为别名,加入aliases集合中。
例如:
<bean name="ZHU,DA,CHANG" class="service.impl.Teacher">
<property name="name" value="张三">property>
<property name="age" value="30">property>
bean>
这里的beanName为"ZHU",别名为“DA”,“CHANG"
<bean id="teacher" name="zhudachang" class="service.impl.Teacher">
<property name="name" value="张三">property>
<property name="age" value="30">property>
bean>
这里的beanName为"teacher",别名为“zhudachang”
2、parseBeanDefinitionElement(ele, beanName, containingBean)方法:见方法3详解
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
//将beanName封装成BeanEntry对象
this.parseState.push(new BeanEntry(beanName));
//获取class类属性
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 {
//创建GenericBeanDefinition,并设置父类名称,通过className获取class并设置
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析设置各种属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//设置description信息
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析元数据
parseMetaElements(ele, bd);
//设置LookupOverride
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//设置ReplacedMethod
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析设置构造函数节点
parseConstructorArgElements(ele, bd);
//解析设置子节点属性
parsePropertyElements(ele, bd);
//解析设置Qualifier
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;
}
1、parseBeanDefinitionAttributes(ele, beanName, containingBean, bd)方法,见方法4详解
2、parseLookupOverrideSubElements(ele, bd.getMethodOverrides())
该方法主要解析子节点中的< lookup-method >标签,该标签处理Bean中属性为原型模式,也就是每次获取该属性时都会新创建一个对象。
如:Teacher类中声明了Address属性,而我们的Address是prototype原型模式,也就是每次获取该值都会创建一个新的对象,而Teacher是一个单例,获取该类时,每次都从缓存中获取,导致类中的Adress也是一个单例,这里就是为后续处理该问题作准备。后续文章会专门讲解这个的用法。
<bean name="address" class="service.Address" scope="prototype">bean>
<bean id="teacher" name="teacher" class="service.impl.Teacher" >
<lookup-method name="getAddress" bean="address">lookup-method>
bean>
3、parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
<bean name="address" class="service.Address" scope="prototype">bean>
<bean id="teacher" name="teacher" class="service.impl.Teacher" >
<replaced-method name="getAddress" replacer="addressMethodReplacer">replaced-method>
bean>
4、parseConstructorArgElements(ele, bd)方法,见方法5详解
5、parsePropertyElements(ele, bd)方法见方法9详解
// 解析设置singleton属性
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
// singleton属性以被scope属性代替
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());
}
// 解析设置abstract属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
// 解析设置lazy-init属性, 默认为false
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
// 解析设置autowire属性
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
// 解析设置dependency-check属性
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
// 解析设置depends-on属性
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
// 解析设置autowire-candidate属性
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(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));
}
// 解析设置primary属性
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
// 解析设置init-method属性
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!"".equals(initMethodName)) {
bd.setInitMethodName(initMethodName);
}
}
else {
if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
}
// 解析设置destroy-method属性
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);
}
}
// 解析设置factory-method属性
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
// 解析factory-bean属性
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
parseConstructorArgElement((Element) node, bd);
}
}
这里遍历子节点中的< constructor-arg >标签,对其属性进行解析封装,parseConstructorArgElement((Element) node, bd)方法见方法6详解
<bean id="address" class="service.Address" >bean>
<bean id="teacher" name="teacher" class="service.impl.Teacher">
<constructor-arg index="0" value="zhangsan">constructor-arg>
<constructor-arg index="1" value="13">constructor-arg>
<constructor-arg index="2" ref="address">constructor-arg>
<constructor-arg index="3" >
<list>
<value>zhudachang1value>
<value>zhudachang2value>
<value>zhudachang3value>
list>
constructor-arg>
bean>
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
//获取index属性
String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
//获取type属性
String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
//获取name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(indexAttr)) {
//如果有index属性
try {
int index = Integer.parseInt(indexAttr);
if (index < 0) {
error("'index' cannot be lower than 0", ele);
}
else {
try {
//校验该index是否>=0,否则抛异常
this.parseState.push(new ConstructorArgumentEntry(index));
//获取其值,可能是通过 value 属性、ref 属性、list 属性等
Object value = parsePropertyValue(ele, bd, null);
//封装成ConstructorArgumentValues对象
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
//设置type值
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
//设置name值
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
error("Ambiguous constructor-arg entries for index " + index, ele);
}
else {
//添加下标及其对应的值
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
}
}
finally {
this.parseState.pop();
}
}
}
catch (NumberFormatException ex) {
error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
}
else {
try {
//如果没有index,此时不做校验
this.parseState.push(new ConstructorArgumentEntry());
//获取当前设置值,可能是通过 value 属性、ref 属性、list 属性等
Object value = parsePropertyValue(ele, bd, null);
//同上面步骤一样
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));
//由于没有下标,这里直接添加集合中
bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
}
finally {
this.parseState.pop();
}
}
}
parsePropertyValue(ele, bd, null)方法,会解析出当前节点对应的引用类型值,见方法7详解
public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
String elementName = (propertyName != null ?
" element for property '" + propertyName + "'" :
" element" );
//获取该节点下的子节点
NodeList nl = ele.getChildNodes();
Element subElement = null;
//如果是List类型,则有子节点。这里会对子节点进行校验
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.
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {
subElement = (Element) node;
}
}
}
//判断是否有该属性
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
//这里不允许有value跟ref共存或者跟有子节点的共存 如list
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) {
//获取属性值并将该属性值封装成RuntimeBeanReference 对象
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值,则封装成TypedStringValue
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;
}
}
parsePropertySubElement(subElement, bd)方法对子节点进行解析,见方法8详解
public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
//判断节点标签是否是默认命名空间,不是则走自定义逻辑
if (!isDefaultNamespace(ele)) {
return parseNestedCustomElement(ele, bd);
}
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
//如果是Bean标签,则进行解析,并封装成BeanDefinitionHolder
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
//判断该节点是否有自定义标签,有则调用自定义逻辑处理,补充新的解析内容进来
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
}
else if (nodeNameEquals(ele, REF_ELEMENT)) {
// 如果是ref,引用其它Bean,获取引用的beanName名称
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
// 获取父类beanName
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean' or 'parent' is required for element", ele);
return null;
}
}
if (!StringUtils.hasText(refName)) {
error(" element contains empty target attribute", ele);
return null;
}
//封装成RuntimeBeanReference
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
ref.setSource(extractSource(ele));
return ref;
}
//解析idref节点
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
return parseIdRefElement(ele);
}
//解析value
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultValueType);
}
//解析null
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
// It's a distinguished null value. Let's wrap it in a TypedStringValue
// object in order to preserve the source location.
TypedStringValue nullHolder = new TypedStringValue(null);
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
//解析Array数组
else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
//解析List集合
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd);
}
//解析Set集合
else if (nodeNameEquals(ele, SET_ELEMENT)) {
return parseSetElement(ele, bd);
}
//解析Map集合
else if (nodeNameEquals(ele, MAP_ELEMENT)) {
return parseMapElement(ele, bd);
}
//解析props
else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
return parsePropsElement(ele);
}
else {
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
1、list节点的解析,获取该节点下的子节点,遍历调用parsePropertySubElement,并将每个子节点添加至Collection中。
2、其它集合Map、Set、Array等的解析过程也跟list类似。
以上我们介绍了< constructor-arg >标签的解析过程,下面来看下
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//如果是默认命名空间标签且是property属性的话,进行解析
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
parsePropertyElement((Element) node, bd);
}
}
}
public void parsePropertyElement(Element ele, BeanDefinition bd) {
//获取name属性值
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;
}
//解析获取其值,该方法在前面的解析中有讲解过,这里不做讲解
Object val = parsePropertyValue(ele, bd, propertyName);
//根据名称、对象值封装成PropertyValue
PropertyValue pv = new PropertyValue(propertyName, val);
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
xml配置案例如下:
<bean id="address" class="service.Address" scope="prototype">bean>
<bean id="teacher" class="service.impl.Teacher">
<property name="name" value="zhudachang">property>
<property name="age" value="11">property>
<property name="address" ref="address">property>
bean>
到这里我们的解析工作就完成了,下面回到方法1中,解析后需要将BeanDefinition注册到上下文缓存中,见方法10详解
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 获取beanName名称
String beanName = definitionHolder.getBeanName();
//注册到缓存中
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//获取别名集合,注册到上下文的别名缓存中
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
1、我们看到传进来的是BeanDefinitionRegistry 注册器,我们可以把它当成管理上下文的工具类吧,使用它可以操作上下文的部分增删改查工作
2、registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())方法,见方法11详解
3、registry.registerAlias(beanName, alias)方法,见方法13详解
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");
//如果是AbstractBeanDefinition,则校验
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//判断缓存中是否存在了该beanName的BeanDefinition
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 {
//检查下当前bean工厂是否开始创建工作,这里是为了加锁
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//将当前beanDefinition放入缓存中
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 {
// 将当前beanDefinition放入缓存中
this.beanDefinitionMap.put(beanName, beanDefinition);
//将beanName加入缓存中
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//如果Bean存在于缓存中,并且的单例的,这里需要重置
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
1、((AbstractBeanDefinition) beanDefinition).validate();
该方法用于校验节点中不能同时存在factory-method属性和子节点< lookup-method >、< replaced-method >。这个if语句是为了确保,上述两者不能共存,否则就会报错。这是因为,如果给一个 Bean 配置了工厂方法,那么它会由工厂方法来创建,而不是 Spring 默认的方式创建,这种情况下无法进行方法的覆盖。因此,这里的判断是为了确保配置信息没有出现冲突。
public void validate() throws BeanDefinitionValidationException {
if (hasMethodOverrides() && getFactoryMethodName() != null) {
throw new BeanDefinitionValidationException(
"Cannot combine factory method with container-generated method overrides: " +
"the factory method must create the concrete bean instance.");
}
if (hasBeanClass()) {
prepareMethodOverrides();
}
}
2、resetBeanDefinition(beanName)方法,见方法12详解
protected void resetBeanDefinition(String beanName) {
// 从合并的MergedBeanDefinition缓存中移除
clearMergedBeanDefinition(beanName);
//这里移除了很多处缓存,如IOC三级缓存等
destroySingleton(beanName);
// 通知后置处理器进行重置处理
for (BeanPostProcessor processor : getBeanPostProcessors()) {
if (processor instanceof MergedBeanDefinitionPostProcessor) {
((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
}
}
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
//当前遍历的BeanDefinition的parentName为beanName,则递归调用resetBeanDefinition进行重置
if (bd != null && beanName.equals(bd.getParentName())) {
resetBeanDefinition(bdName);
}
}
}
}
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
synchronized (this.aliasMap) {
//如果别名缓存中已经存在该数据,则移除
if (alias.equals(name)) {
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}
else {
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
//如果别名已经注册过,直接返回
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
registeredName + "' with new target name '" + name + "'");
}
}
//检查name和alias是否存在循环引用。例如A的别名为B,B的别名为A
checkForAliasCircle(name, alias);
//加入缓存
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
至此,Spring 加载默认命名空间的 BeanDefinition 的过程就全部分析完了,可以说这是 BeanFactory 实例化前最复杂的逻辑了。我们梳理一下流程:
1、Spring判断是否默认命名空间,加载默认解析器进行解析
2、使用默认命名空间解析完成后得到初步的BeanDefinition对象,再调用自定义命名空间进行处理判断是否需要补充处理。
3、将解析的BeanDefinition 加入beanDefinitionMap缓存中,将beanName加入beanDefinitionNames缓存中,将aliases加入到aliasMap缓存中。
后面我们会继续讲解自定义命名空间的处理过程。