loadBeanDefinitions方法源码跟踪(二)
因为字数超过了限制,所以分成了三篇,承接上篇:
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