因为字数超过了限制,所以分成了三篇,承接上篇:

https://www.jianshu.com/p/a0cfaedf3fc5

代码过宽,可以shift + 鼠标滚轮 左右滑动查看

3.parseDefaultElement

先跟踪一个bean标签,下面是对应的配置文件

<!--配置mapper.java扫描-->
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.mrdear.mapper"/>
<property name="properties">
<value>
mappers=tk.mybatis.mapper.common.Mapper
</value>
</property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

因为是bean标签,走的默认的名称空间方法,所以走这个标签的方法:

//3.如果该标签属于beans的名称空间,则进入这个方法
//xmlns="http://www.springframework.org/schema/beans"
parseDefaultElement(ele, delegate);

这个方法的实现在DefaultBeanDefinitionDocumentReader类中,因为标签下有多个子标签,所以每个子标签对应着一个方法

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
// 如果是嵌套的beans,那么就会重新调用标记2中的一个方法进行递归
doRegisterBeanDefinitions(ele);
}
} /**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*
* 处理bean元素,解析成bean definition并注册到工厂中
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //3.1通过代理解析bean元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) { //3.2如果有要求的话渲染beanDefinition
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try { // Register the final decorated instance.
//3.3注册最终被渲染的实例到工厂中
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));
}
}

3.1 parseBeanDefinitionElement

跟踪3.1标记的方法

进入BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法

//3.1通过代理解析bean元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); /**
* 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}.
*
* 解析bean元素。如果解析过程中发生错误则返回空
*/
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
} public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { //拿bean标签上的id
String id = ele.getAttribute(ID_ATTRIBUTE); //拿bean标签上的name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<String>(); //有name属性进入
if (StringUtils.hasLength(nameAttr)) { //name属性对应的name值如果有分隔符",; ",那么切分成数组
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); //这些name值就是别名
aliases.addAll(Arrays.asList(nameArr));
} //指定了id就用id值作为bean名称
String beanName = id; //如果没有id,但是指定了name,就用name值作为bean名称
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { //拿第一个name值作为bean名称,其余的还是别名
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
} if (containingBean == null) { //检查bean名称和别名是否已经被使用了,如果用了就报错
//同时把这个bean的名称和别名加入代理的usedNames属性中
//private final Set<String> usedNames = new HashSet<String>();
checkNameUniqueness(beanName, aliases, ele);
} //直接进入这个方法
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) { //既没有指定id,也没有指定name就走这里面
if (!StringUtils.hasText(beanName)) {
try { //前面containingBean传递时为null,这里不走这个方法
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else { //生成一个bean名称,beanName
//如果这个bean是内部bean,全限定名后加#号再加哈希值
//如果是顶层bean,那么后面加#号再从0开始加数字,id已被注册数字就增1,直到唯一
//比如:tk.mybatis.spring.mapper.MapperScannerConfigurer#0
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)) { //如果该类名没有被使用,那么注册该类名作为别名,比如:
//tk.mybatis.spring.mapper.MapperScannerConfigurer作为
//tk.mybatis.spring.mapper.MapperScannerConfigurer#0的别名
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); //返回beanDefinition的持有者
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} return null;
} /**
* 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.
*
* 不关注名称和别名,只解析bean definition自身
*/
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) { //解析的时候放入,解析完成弹出,这里放入bean标签,
//如果还嵌套有子标签,则后续放入子标签
//子标签先弹出
this.parseState.push(new BeanEntry(beanName)); String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) { //如果有指定class属性,则拿到class属性值
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
} try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) { //如果有指定parent属性,则拿到parent属性值
parent = ele.getAttribute(PARENT_ATTRIBUTE);
} //3.1.1创建BeanDefinition并设置两属性
AbstractBeanDefinition bd = createBeanDefinition(className, parent); //3.1.2将bean标签上的属性设置到bean definition中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //如果bean标签下有子标签为description,拿到标签中的文本,设置到bean definition中
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //如果bean标签下有子标签为meta,拿到他的key和value属性,设置到bean definition中
parseMetaElements(ele, bd); //如果bean标签下有子标签为lookup-method,拿到他的name和bean属性,设置到bean definition中
parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //如果bean标签下有子标签为replaced-method,设置bean definition
parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //如果bean标签下有子标签为constructor-arg,设置bean definition的构造方式
parseConstructorArgElements(ele, bd); //这个标签比较常用,为Property标签
//3.1.3解析Property的属性设置到bean definition中
parsePropertyElements(ele, bd); //有qualifier子标签才走这个方法
parseQualifierElements(ele, bd); //设置资源
bd.setResource(this.readerContext.getResource()); //这里为null
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;
}

3.1.1 createBeanDefinition

跟踪标记3.1.1

//3.1.1创建BeanDefinition并设置两属性
AbstractBeanDefinition bd = createBeanDefinition(className, parent); /**
* Create a bean definition for the given class name and parent name.
*
* 通过给定的className和parentName创建beanDefinition
*/
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
throws ClassNotFoundException { return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
} /**
* 此方法是BeanDefinitionReaderUtils的静态方法
*
* Create a new GenericBeanDefinition for the given parent name and class name,
* eagerly loading the bean class if a ClassLoader has been specified.
*
* 通过给定的parentName和className穿件一个新的GenericBeanDefinition
* 如果指定了ClassLoader,就提前加载bean class
*/
public static AbstractBeanDefinition createBeanDefinition(
String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException { GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) { //接受的属性是Object类型
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else { //接受的属性是Object类型
bd.setBeanClassName(className);
}
}
return bd;
}

3.1.2 parseBeanDefinitionAttributes

跟踪标记方法3.1.2

此方法在BeanDefinitionParserDelegate类中

//3.1.2将bean标签上的属性设置到bean definition中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); /**
* Apply the attributes of the given bean element to the given bean * definition.
*
* 将bean标签上的属性设置到bean definition中
*/
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) { //bean标签上已经没有singleton属性了,用scope代替,所以出现就报错
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));
} //此处containingBean为空
else if (containingBean != null) { // Take default from containing bean in case of an inner bean definition.
// 如果是一个内部的bean definition,用包含的bean的default
bd.setScope(containingBean.getScope());
} //是否有abstract属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
} String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); //lazyInit如果没有设置则为默认值,默认值用的代理类中defaults属性,
//也就是this.defaults
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
} bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); //默认值用的代理类中defaults属性,不进行autowire
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire)); //默认不进行依赖检查
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 { //没有init-method属性,就拿代理类defaults属性的
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 { //没有destroy-method属性,就拿代理类defaults属性的
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;
}

这样,bean标签上的属性也就解析完成了,对其属性的描述不管设置了还是没有设置的,都有相应的值对应到bean definition中。接下来就要解析,bean标签下的子标签了。

3.1.3 parsePropertyElements

跟踪3.1.3标记的方法

此方法在BeanDefinitionParserDelegate类中实现

//3.1.3解析Property的属性设置到bean definition中
parsePropertyElements(ele, bd); /**
* Parse property sub-elements of the given bean element.
* 解析bean标签下property子标签
*/
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)) { //标签名为property才能进入,进入这个方法
parsePropertyElement((Element) node, bd);
}
}
} /**
* Parse a property element.
*/
public void parsePropertyElement(Element ele, BeanDefinition bd) { //拿到property标签的name属性
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
} //解析的时候放入,解析完成弹出,这里放入property标签,
//这里面还存有bean父标签,子标签解析完成后先弹出
this.parseState.push(new PropertyEntry(propertyName));
try { //bean标签下可以有多个property,但是不能重复name属性
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
} //进入这个方法,查看是怎么解析property标签属性的
Object val = parsePropertyValue(ele, bd, propertyName); //将name属性和对应的value放入
PropertyValue pv = new PropertyValue(propertyName, val); //解析property标签的子标签meta,
//拿到meta的key和value属性,设置到PropertyValue中
parseMetaElements(ele, pv); //这里没有实现,为null
pv.setSource(extractSource(ele)); //将PropertyValue添加到bean definition中
bd.getPropertyValues().addPropertyValue(pv);
}
finally { //解析的时候放入,解析完成弹出,这里放入property标签
this.parseState.pop();
}
} /**
* Get the value of a property element. May be a list etc.
* Also used for constructor arguments, "propertyName" being null in this case.
*
* 拿到property标签的value值,可能是list
* 也被constructor标签使用,这种情况propertyName为null
*/
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { //如果propertyName为null,则是constructor-arg标签
//否则为property标签
String elementName = (propertyName != null) ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element"; // Should only have one child element: ref, value, list, etc.
//不管是哪种标签,下面都应该只有一个子标签: ref, value, list等.
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.
//除开description和meta标签,子标签最多只能有一个
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {
subElement = (Element) node;
}
}
} //看标签属性用的是value还是ref
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); //value和ref属性不能同时存在,如果有子标签,则value和ref都不能存在,否则报错
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的情况
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的情况
else if (hasValueAttribute) {
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
valueHolder.setSource(extractSource(ele));
return valueHolder;
} //子标签不为null的情况,进入这个方法查看
else if (subElement != null) {
return parsePropertySubElement(subElement, bd);
}
else { // Neither child element nor "ref" or "value" attribute found.
//没指定ref或者value或者子标签,返回null
error(elementName + " must specify a ref or value", ele);
return null;
}
} /**
* 这个方法还是在BeanDefinitionParserDelegate中
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
return parsePropertySubElement(ele, bd, null);
} /**
* Parse a value, ref or collection sub-element of a property or
* constructor-arg element.
*
* 解析property或者constructor-arg标签的子标签,可能为value, ref或者集合
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) { //如果这个子标签不属于beans的名称空间,则走这个方法
if (!isDefaultNamespace(ele)) {
return parseNestedCustomElement(ele, bd);
} //如果是bean子标签,则走这个方法
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
} //如果是ref子标签,则走这个方法
else if (nodeNameEquals(ele, REF_ELEMENT)) { // A generic reference to any name of any bean.
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
boolean toParent = false;
if (!StringUtils.hasLength(refName)) { // A reference to the id of another bean in the same XML file.
refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
if (!StringUtils.hasLength(refName)) { // A reference to the id of another bean in a parent context.
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean', 'local' or 'parent' is required for <ref> element", ele);
return null;
}
}
}
if (!StringUtils.hasText(refName)) {
error("<ref> element contains empty target attribute", ele);
return null;
}
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);
} //否则返回null,报错
else {
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
} /**
* Return a typed String value Object for the given value element.
*
* 通过指定的value标签,返回指定的字符串value对象
*/
public Object parseValueElement(Element ele, String defaultTypeName) { // It's a literal value.
//拿到value中的文本,包括回车、tab制表符、空格
String value = DomUtils.getTextValue(ele); //有无type属性
String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
String typeName = specifiedTypeName;
if (!StringUtils.hasText(typeName)) { //没有就用入参defaultTypeName
typeName = defaultTypeName;
}
try {
TypedStringValue typedValue = buildTypedStringValue(value, typeName); //这里设置为空
typedValue.setSource(extractSource(ele)); //这里为空字符串
typedValue.setSpecifiedTypeName(specifiedTypeName); //返回typedValue
return typedValue;
}
catch (ClassNotFoundException ex) {
error("Type class [" + typeName + "] not found for <value> element", ele, ex);
return value;
}
}

3.2 decorateBeanDefinitionIfRequired

在生成了BeanDefinitionHolder以后,如果需要的话应该通过代理类对bean definition进行渲染。

跟踪标记3.2的方法

该方法的实现在BeanDefinitionParserDelegate类中

//3.2如果有要求的话渲染beanDefinition
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
} public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) { BeanDefinitionHolder finalDefinition = definitionHolder; // Decorate based on custom attributes first.
// 首先基于自定义属性进行渲染
// 也就是bean标签上的属性,也就是node
// 只有当这个node不属于名称空间beans才会进行渲染,这里就不进去看了
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
} // Decorate based on custom nested elements.
// 然后根据标签内嵌套的子标签进行渲染
// 这里是不属于名称空间beans的子标签才会进行渲染
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}

3.3 registerBeanDefinition

最终将完成的bean definition注册到工厂中

跟踪标记3.3的方法

//3.3注册最终被渲染的实例到工厂中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); /**
* Register the given bean definition with the given bean factory.
*
* 注册bean definition
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException { // Register bean definition under primary name. // 3.3.1注册bean definition的beanName
// 比如tk.mybatis.spring.mapper.MapperScannerConfigurer#0
String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. // 如果有别名的话,为bean name注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) { //3.3.2注册别名
registry.registerAlias(beanName, alias);
}
}
}

3.3.1 registerBeanDefinition

跟踪标记3.3.1的方法

// 3.3.1注册bean definition的beanName
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); @Override
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 { //做一个验证,静态工厂方法和覆盖方法不能组合使用
//如果bean definition中的beanClass属性不是String类型而是Class类型
//那么就要验证和准备这个bean定义的覆盖方法,检查指定名称的方法是否存在
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
} BeanDefinition oldBeanDefinition; //查看beanName是否已经被注册在工厂的beanDefinitionMap属性中
oldBeanDefinition = this.beanDefinitionMap.get(beanName); //已经被注册走这个方法,这里不查看
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else { //这里面代表beanName还没有被注册
//然后根据阶段不同又有一层判断
if (hasBeanCreationStarted()) { //这个阶段是bean已经开始创建
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else { // Still in startup registration phase // 仍然处于启动时的注册阶段
// 所以这里走这个方法
//beanDefinitionMap是工厂的一个属性,ConcurrentHashMap类型
//他保存所有解析好的bean Definition的名称和实例的映射
this.beanDefinitionMap.put(beanName, beanDefinition); //beanName也单独使用了一个ArrayList来保存,方便遍历
this.beanDefinitionNames.add(beanName); //如果该bean definition是手动注册的,还要从manualSingletonNames中
//移除bean definition的beanName,还要从manualSingletonNames中是LinkedHashSet
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
} //这里跳过
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

3.3.2 registerAlias

跟踪3.3.2方法

//3.3.2注册别名
registry.registerAlias(beanName, alias); @Override
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
if (alias.equals(name)) { //移除别名中的beanName
//aliasMap是ConcurrentHashMap类型,保存别名和beanName的映射
this.aliasMap.remove(alias);
}
else {
String registeredName = this.aliasMap.get(alias); //如果别名对应beanName已经被注册,则不需要再注册一次
//别名不允许被覆盖
if (registeredName != null) {
if (registeredName.equals(name)) { // An existing alias - no need to re-register
return;
}
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
} //再检查一遍,aliasMap中不能已经存在name和alias
checkForAliasCircle(name, alias); //工厂的aliasMap属性保存别名,那么alias已被注册
this.aliasMap.put(alias, name);
}
}

这样,spring配置文件中为bean标签的解析和加载,也就跟踪完了。

然后再看下非默认名称空间的标签的解析和加载。

因为字数超过了限制,所以分成了三篇,点击下篇继续阅读

https://www.jianshu.com/p/6e0f6fd1cbbd

总结

3

  • 走解析默认元素的方法。根据beans名称空间下,不同的标签有不同的子方法,对于<bean>标签来说,主要分为三步:

    • 3.1 通过代理 delegate 解析 bean 元素生成 BeanDefinitionHolder
    • 如果有必要的话,利用非默认名称空间的属性和子标签,渲染 BeanDefinitionHolder 中的 BeanDefinition
    • 注册最终被渲染的实例到工厂中。分两步,一步注册 BeanDefinition ,其实就是将 beanName 和 BeanDefinition 放入 beanDefinitionMap 中,beanName 放入 beanDefinitionNames中;一步注册别名,将 alias、name放入到 aliasMap 中

——————————————————————————————————

  • 3.1
  • 获取元素上的 id、name 属性,id 作为 beanName,name 作为别名。如果没有指定 id,取 name 的一个值作为 beanName,别名中移除该值。
  • 解析元素生成 BeanDefinition
  • 如果属性没有指定 id 也没有指定 name,利用 beanDefinition 生成一个 beanName。当这个bean是内部bean,类的全限定名加#号再加哈希值;当是顶层bean,类的全限定名加#号再从0开始加数字,id已被注册数字就增1,直到唯一。有了 beanName,再以类的全限定名作为别名。
  • 利用 BeanDefinition ,beanName ,别名,生成 BeanDefinitionHolder 并返回

——————————————————————————————————

  • 解析元素生成 BeanDefinition

    • 根据 bean 元素中的 class 属性和 parent 属性创建 BeanDefinition
    • 将 bean 标签上的属性设置到 BeanDefinition 中,一些未明确指定的属性采用代理 delegate 中的 defaults 值
    • 解析 bean 标签下的子标签,如 Property 、constructor-arg 等,将其键值对添加到 BeanDefinition 中
    • 返回 BeanDefinition

loadBeanDefinitions方法源码跟踪(二)的更多相关文章

  1. loadBeanDefinitions方法源码跟踪(一)

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractBeanDe ...

  2. loadBeanDefinitions方法源码跟踪(三)

    因为字数超过了限制,所以分成了三篇,承接上篇: https://www.jianshu.com/p/46e27afd7d96 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 4.parseCus ...

  3. erlang下lists模块sort(排序)方法源码解析(二)

    上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...

  4. obtainFreshBeanFactory方法源码跟踪

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractApplic ...

  5. prepareRefresh方法源码跟踪

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractApplic ...

  6. postProcessBeanFactory方法源码跟踪

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractApplic ...

  7. prepareBeanFactory方法源码跟踪

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractApplic ...

  8. erlang下lists模块sort(排序)方法源码解析(一)

    排序算法一直是各种语言最简单也是最复杂的算法,例如十大经典排序算法(动图演示)里面讲的那样 第一次看lists的sort方法的时候,蒙了,几百行的代码,我心想要这么复杂么(因为C语言的冒泡排序我记得不 ...

  9. 十、Spring之BeanFactory源码分析(二)

    Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ...

随机推荐

  1. 《JavaScript高级程序设计》读书笔记(三)基本概念第一小节

    内容---语法 本小节---数据类型 本小节 undefined,null,Boolean---流程控制语句---理解函数 任何语言的核心都必然会描述这门语言最基本的工作原理.而描述的内容通常都要涉及 ...

  2. Maven打包项目失败;报错:Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.1.1:war (default-war) on project Hello: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/we

    报错信息: E:\MIKEY\mikey\HTML5\TestMaven_01>mvn package [INFO] Scanning for projects... [INFO] [INFO] ...

  3. Struts笔记二:栈值的内存区域及标签和拦截器

    值栈和ognl表达式 1.只要是一个MVC框架,必须解决数据的存和取的问题 2.struts2利用值栈来存数据,所以值栈是一个存储数据的内存结构 1.  ValueStack是一个接口,在struts ...

  4. nginx 变量相关的map模块与split_clients模块及geo模块和geoip模块及keepalive介绍

    map 模块指令默认编译进nginx的 Syntax: map string $variable { ... } # 表示string匹配到{}里的值或变量赋值给$variable Default: ...

  5. C12Test5 record

  6. Duilib热键

    转载:https://www.zhaokeli.com/article/8288.html 在initwindow中注册热键 //生成热键标识,需要保存起来退出时销毁使用 int m_HotKeyId ...

  7. Linux命令:tcpdump命令

    tcpdump网络抓包工具 格式:tcpdump [options] [表达式] optinos选项 -i any:监听所有网络接口 -i eth0:监听指定的网络接口(eth0) -D:列出所有可用 ...

  8. Qt 调用本地浏览器打开URL

    点击Qt某些控件,查找本地浏览器打开前端传递的URL. 方法一:直接写死本地浏览器地址 QString programAdress = "C:\Program Files (x86)\Goo ...

  9. ActiveMQ--模式(队列模式/主题模式)

    两种模式:队列模式/主题模式 pom.xml <dependency> <groupId>org.apache.activemq</groupId> <art ...

  10. angular 自定义服务封装自定义http请求

    在angular中将http请求,放置在一起封装成服务,可减少代码重复,方便使用 var ngpohttprest = angular.module('ngpohttprest', []); ngpo ...