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)) {
this.parseDefaultElement(ele, delegate); // 解析默认标签
} else {
delegate.parseCustomElement(ele); // 解析自定义标签
}
}
}
} else {
delegate.parseCustomElement(root); // 解析自定义标签
}
}
默认标签:import、alias、bean、beans四种标签的解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, "bean")) {
this.processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);
}
}
bean标签:(很重要)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// step1:元素解析
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// step2:如果子节点下还有自定义标签,则对其进行解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// step3:对bdHoldr进行注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
BeanDefinitionStoreException ex = var5;
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
}
// step4:发送注册事件
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
bean标签的解析和注册的时序图如下所示:
step1:parseBeanDefinitionElement:
在parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)方法中, 其实一共执行了如下4个步骤:
① 提取Element元素中的“id”和“name”属性,并将name解析为aliases,然后为 beanName赋值。
② 解析其他属性并封装到GenericBeanDefinition类型的实例中。
③ 如果发现bean没有指定beanName,那么使用默认规则生成beanName。
④ 将获取到的信息封装到BeanDefinitionHolder类型的实例中。
举例:bean.xml中的一个bean
<!-- bean 标签演示 -->
<bean id="m416" class="com.muse.springdemo.entity.Gun">
<property name="name" value="M416"/>
<property name="bulletNums" value="45"/>
<property name="desc" value="非常好用的一把枪"/>
</bean>
关于BeanDefinitionParserDelegate类parseBeanDefinitionElement方法的源码部分,如下页所示:
/**
* 解析提供的<bean>元素。如果在解析期间发生错误,可能返回null。错误被报告给org.springframework.beans.factory.parse.problemreporter
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
/**
* 解析提供的<bean>元素。如果在解析期间发生错误,可能返回null。错误被报告给org.springframework.beans.factory.parse.problemreporter
*/
// eg1:containingBean=null
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE); // eg1: id="m416"
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // eg1: name=""
/** 1: 将配置中的"name"属性,解析为aliases */
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) { // eg1:nameAttr=""
// 例如:nameAttr="made,in;china",delimiters=",; ",返回数组:[made, in, china]
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); // ",; "
aliases.addAll(Arrays.asList(nameArr));
}
/** 2: 如果配置中没有指定"id"属性,并且aliases不为空,则取aliases列表中的第一个名称作为beanName */
String beanName = id; // eg1: beanName="m416"
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) // eg1:aliases.size()=0
beanName = aliases.remove(0);
/** 3: 校验beanName和aliases是否被使用过 */
if (containingBean == null) // eg1: containingBean=null
checkNameUniqueness(beanName, aliases, ele);
/** 4: 解析配置文件中其它的属性,并封装为GenericBeanDefinition实例 */
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) { // eg1:beanName="m416"
try {
if (containingBean != null)
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases); // eg1:aliases.size()=0
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); // eg1:beanName="m416",aliasesArray=[]
}
return null;
}
checkNameUniqueness(String beanName, List<String> aliases, Element beanElement):
/**
* 验证指定的beanName和aliases是否已经在当前级别的bean元素嵌套中使用。
*/
// eg1: beanName="m416", aliases.size()=0
protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
String foundName = null;
/** 1: 如果beanName已经被使用过,则将beanName赋值给foundName变量 */
if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) // eg1: usedNames.size()=0
foundName = beanName;
/** 2: 如果aliases中存在已经被使用过的名称,则将aliase中第一个校验出已经被使用过的名称复制给foundName */
if (foundName == null) // eg1: foundName=null
foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases); // eg1: usedNames.size()=0,aliases.size()=0
/** 3: 如果foundName不为null,则表明存在被使用过的beanName或aliase,抛出异常即可 */
if (foundName != null) // eg1: foundName=null
error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);
this.usedNames.add(beanName); // eg1: beanName="m416"
this.usedNames.addAll(aliases); // eg1: aliases.size()=0, usedNames=["m416"]
}
/**
* 解析bean定义本身,而不考虑名称或别名。如果在解析bean定义期间发生问题,可能返回null。
*/
// eg1:containingBean=null,beanName="m416"
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
/** 1:尝试获得"class"属性 */
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) // eg1:true
className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); // eg1:className="com.muse.springdemo.entity.Gun"
/** 2:尝试获得"parent"属性 */
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) // eg1:false
parent = ele.getAttribute(PARENT_ATTRIBUTE);
try {
/** 3:创建GenericBeanDefinition实例对象 */
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
/**
* 4:解析默认bean的各个属性(其中解析内容包括:singleton属性、scope属性、abstract属性、lazy-init属性、autowire属性、
* depends-on属性、autowire-candidate属性、primary属性、init-method属性、destroy-method属性、factory-method属性、factory-bean属性)
*/
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); // eg1:null,"description"
/** 5:解析元数据 */
parseMetaElements(ele, bd);
/** 6:解析lookup-method属性 */
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
/** 7:解析replaced-method属性 */
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
/** 8:解析构造函数参数 */
parseConstructorArgElements(ele, bd);
/** 9:解析property子元素 */
parsePropertyElements(ele, bd);
/** 10:解析qualifier子元素 */
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd; // 返回组装好的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:创建GenericBeanDefinition实例对象 */
创建BeanDefinition的这部分内容,是通过调用createBeanDefinition方法实现的。但是, 在介绍整个方法内部逻辑之前,我们先来了解一下BeanDefinition,它到底是做什么用的? BeanDefinition是配置文件中元素标签在Spring容器中的表现形式,也就是说,它 是用来承载bean信息的。在配置文件中可以定义父级和子集,它们分别由 RootBeanDefinition和ChildBeanDefinition表示。而如果没有父级的话,则用 RootBeanDefinition表示。而GenericBeanDefinition是从2.5版本之后加入进来的,用于为 bean文件配置属性属性定义提供一站式服务
/**
* 为给定的类名和父类名创建一个bean定义。
*/
// eg1: className="com.muse.springdemo.entity.Gun", parentName=null
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) throws ClassNotFoundException {
return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
}
//为给定的父类名创建一个新的GenericBeanDefinition,如果指定了类加载器,则立即加载bean类
// eg1:className="com.muse.springdemo.entity.Gun" parentName=null, classLoader=null
public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName); // parentName=null
if (className != null) { // eg1:className="com.muse.springdemo.entity.Gun"
if (classLoader != null) { // classLoader=null
bd.setBeanClass(ClassUtils.forName(className, classLoader));
} else {
bd.setBeanClassName(className); // eg1:className="com.muse.springdemo.entity.Gun"
}
}
return bd;
}
/* 4:解析默认bean的各个属性 */
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd) bean属性的解析:
在parseBeanDefinitionAttributes方法中,通过解析配置中的bean信息,并将其赋值给 AbstractBeanDefinition实例对象。其中解析内容包括:singleton属性、scope属性、abstract属性、lazy-init属性、autowire属性、 * depends-on属性、autowire-candidate属性、primary属性、init-method属性、destroy-method属性、factory-method属性、factory-bean属性
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
/** 1:向bd中设置scope变量的值 */
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) // eg1:false,判断是否存在"singleton"属性
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) // eg1:false,判断是否存在"scope"属性
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
else if (containingBean != null) // eg1:containingBean=null
bd.setScope(containingBean.getScope());
/** 2:向bd中设置abstractFlag变量的值 */
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) // eg1:false,判断是否存在"abstract"属性
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
/** 3:向bd中设置lazyInit变量的值 */
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); // eg1:lazyInit="default"
if (isDefaultValue(lazyInit))
lazyInit = this.defaults.getLazyInit(); // eg1:lazyInit="false"
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
/** 4:向bd中设置autowireMode变量的值 */
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); // eg1:autowire="default"
bd.setAutowireMode(getAutowireMode(autowire)); // eg1:getAutowireMode(autowire)=AUTOWIRE_NO 默认为0
/** 5:向bd中设置dependsOn变量的值 */
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { // eg1:false,判断是否存在"depends-on"属性
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); // ",; "
}
/** 6:向bd中设置autowireCandidate变量的值 */
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); // eg1:autowireCandidate="default,获得"autowire-candidate"属性
if (isDefaultValue(autowireCandidate)) {
String candidatePattern = this.defaults.getAutowireCandidates(); // 默认值为null
if (candidatePattern != null) { // eg1: candidatePattern=null
String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
} else bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
/** 7:向bd中设置primary变量的值 */
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) // eg1:false,判断是否存在"primary"属性
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
/** 8:向bd中设置initMethodName和enforceInitMethod变量的值 */
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { // eg1:false,判断是否存在"init-method"属性
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
bd.setInitMethodName(initMethodName);
} else if (this.defaults.getInitMethod() != null) { // eg1:defaults.getInitMethod()=null
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
/** 9:向bd中设置destroyMethodName和enforceDestroyMethod变量的值 */
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { // eg1:false,判断是否存在"destroy-method"属性
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
bd.setDestroyMethodName(destroyMethodName);
} else if (this.defaults.getDestroyMethod() != null) { // eg1:defaults.getDestroyMethod()=null
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
/** 10:向bd中设置factoryMethodName变量的值 */
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) // eg1:false,判断是否存在"factory-method"属性
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
/** 11:向bd中设置factoryBeanName变量的值 */
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) // eg1:false,判断是否存在"factory-bean"属性
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
return bd;
}
/** 4:向bd中设置autowireMode变量的值 */
/** 解析给定的autowire属性值int autowire常量 */
@SuppressWarnings("deprecation")
public int getAutowireMode(String attrValue) {
String attr = attrValue;
if (isDefaultValue(attr)) // attr为空,或者 attr值为"default"
attr = this.defaults.getAutowire(); // 从<beans>标签中的default-autowire属性获取默认值
int autowire = AbstractBeanDefinition.AUTOWIRE_NO;
if (AUTOWIRE_BY_NAME_VALUE.equals(attr)) // "byName"
autowire = AbstractBeanDefinition.AUTOWIRE_BY_NAME;
else if (AUTOWIRE_BY_TYPE_VALUE.equals(attr)) // "byType"
autowire = AbstractBeanDefinition.AUTOWIRE_BY_TYPE;
else if (AUTOWIRE_CONSTRUCTOR_VALUE.equals(attr)) // "constructor"
autowire = AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR;
else if (AUTOWIRE_AUTODETECT_VALUE.equals(attr)) // "autodetect"(Spring3.0之后不再支持,被废弃)
autowire = AbstractBeanDefinition.AUTOWIRE_AUTODETECT;
return autowire;
}
/** 5:解析元数据 */
<!-- meta 标签演示 -->
<bean id="m416OfMeta" class="com.muse.springdemo.entity.Gun">
<property name="name" value="M416"/>
<property name="bulletNums" value="45"/>
<meta key="desc" value="非常好用的一把枪"/>
</bean>
@Test
void testMeta() {
Gun gun = beanFactory.getBean("m416OfMeta", Gun.class);
log.info("m416OfMeta={}", gun);
}
运行结果:
使用了meta标签后,配置的desc并不会体现在bean的属性当中,而只是一个额外的声明。 当需要使用里面的信息的时候,可以通过BeanDefinition的getAttribute(key)方法进行获取。对meta的解析:
/** 5:解析元数据 */
parseMetaElements(ele, bd);
/** 解析给定元素下面的meta元素(如果有的话)*/
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
NodeList nl = ele.getChildNodes(); // 获取当前节点的所有子节点列表
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// node节点是候选人元素,并且node节点名称为"meta"
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) { // 只解析meta标签
Element metaElement = (Element) node;
String key = metaElement.getAttribute(KEY_ATTRIBUTE); // meta标签中的key
String value = metaElement.getAttribute(VALUE_ATTRIBUTE); // meta标签中的value
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value); // 封装到BeanMetadataAttribute实例对象中
attribute.setSource(extractSource(metaElement));
attributeAccessor.addMetadataAttribute(attribute); // 将attribute保存到BeanDefinition中
}
}
}
/** 如果node是Element类型,并且 (node属于默认命名空间 或者 node的父节点不是默认命名空间),则返回true */
private boolean isCandidateElement(Node node) {
return (node instanceof Element && (isDefaultNamespace(node) || !isDefaultNamespace(node.getParentNode())));
}
/** 6:解析lookup-method属性 */
lookup-method它的作用是获取器注入。即:获取器注入是一种特殊的方法注入,它是把 一个方法声明为返回某种类型的bean,但实际要返回的bean是在配置文件里面配置的, 此方法可用在设计有些可插拔的功能上,解除程序依赖。
/** 6:解析lookup-method属性 */
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
/**
* 解析给定bean元素的lookup-override子元素
*/
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes(); // 获取当前节点的所有子节点列表
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) { // 只解析lookup-method标签
Element ele = (Element) node;
String methodName = ele.getAttribute(NAME_ATTRIBUTE);
String beanRef = ele.getAttribute(BEAN_ELEMENT);
LookupOverride override = new LookupOverride(methodName, beanRef); // 将lookup-method标签的配置信息封装为LookupOverride实例对象
override.setSource(extractSource(ele));
overrides.addOverride(override); // 将override保存到BeanDefinition中
}
}
}
举例:
public interface Pen {
void print();
}
public class Brush implements Pen {
@Override
public void print() {
System.out.println("Brush print !");
}
}
public class Pencil implements Pen {
@Override
public void print() {
System.out.println("Pencil print !");
}
}
public abstract class Writer {
public void write() {
getPen().print();
}
public abstract Pen getPen();
}
<!-- lookup-method 标签 -->
<bean id="writer" class="com.muse.springdemo.lookupmethod.Writer">
<lookup-method name="getPen" bean="brush"/>
</bean>
<bean id="pencil" class="com.muse.springdemo.lookupmethod.Pencil"/>
<bean id="brush" class="com.muse.springdemo.lookupmethod.Brush"/>
@Test
void testLookupMethod() {
Writer writer = beanFactory.getBean("writer", Writer.class);
writer.write();
}
运行结果:
/** 7:解析replaced-method属性 */
replaced-mothod可以实现方法替换,通过实现MethodReplacer接口,可以在运行时用新的方法替换现有的方法。
举例:
public class Coder {
public void shout() {
System.out.println("老板!我要离职!我不想写代码了!烦死了!");
}
}
public class CoderMethodReplacer implements MethodReplacer {
@Override
public Object reimplement(Object obj, Method method, Object[] args) {
System.out.println("老板!我最爱写代码了!我会一直忠于公司为您工作的!");
return null;
}
}
<!-- replaced-method 标签演示 -->
<bean id="coder" class="com.muse.springdemo.replacedmethod.Coder"/>
<bean id="fakerCoder" class="com.muse.springdemo.replacedmethod.Coder">
<replaced-method name="shout" replacer="replacer"/>
</bean>
<bean id="replacer" class="com.muse.springdemo.replacedmethod.CoderMethodReplacer"/>
@Test
void testReplacedMethod() {
Coder coder = beanFactory.getBean("coder", Coder.class);
coder.shout(); // 输出结果:老板!我要离职!我不想写代码了!烦死了!
Coder coder = beanFactory.getBean("fakerCoder", Coder.class);
coder.shout(); // 输出结果:老板!我最爱写代码了!我会一直忠于公司为您工作的!
}
/** 7:解析replaced-method属性 */
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
/**
* 解析给定bean元素的replaced-method子元素
*/
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes(); // 获取当前节点<replaced-method .../>标签的所有子节点列表
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { // 只解析replaced-method标签
Element replacedMethodEle = (Element) node;
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); // "name"
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); // "replacer"
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT); // "arg-type"
for (Element argTypeEle : argTypeEles) {
String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE); // "match"
match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(extractSource(replacedMethodEle)); // 将replaced-method标签的配置信息保存到replaceOverride实例对象中
overrides.addOverride(replaceOverride); // 将replaceOverride保存到BeanDefinition中
}
}
}
lookup-method和replaced-method都会写进overrides,调用overrides的时候,获取到的就是lookup-method和replaced-method。
/** 8:解析构造函数参数 */
parseConstructorArgElements(ele, bd);
关于构造函数的解析操作,其核心代码是在parsePropertyValue这个方法中的,其处理逻辑如下所示:
① 不处理description属性和meta属性。
② 获取<constructor-arg>标签下的ref属性和value属性。
③ 当发现——
【情况1】同时存在ref属性和value属性;
【情况2】存在ref/value属性 并且存在子元素;任意一种情况时,抛出异常。
④ 如果配置了ref属性,则将ref的属性值保存到RuntimeBeanReference实例对象中。 eg:<constructor-arg ref="xxxx">
⑤ 如果配置了value属性,则将value的属性值保存到TypedStringValue实例对象中。 eg:<constructor-arg value="xxxx">
⑥ 如果配置了子元素,则调用parsePropertySubElement方法进行子元素解析。
⑦ 如果上面3种情况都没配置,则直接抛出异常
举例:
<!-- constructor 标签演示 -->
<bean id="cat" class="com.muse.springdemo.constructor.Cat">
<constructor-arg index="0">
<value>bob</value>
</constructor-arg>
<constructor-arg index="1">
<value>5</value>
</constructor-arg>
</bean>
@AllArgsConstructor
@Data
public class Cat {
private String name;
private int age;
}
@Test
void testConstructor() {
Cat cat = beanFactory.getBean("cat", Cat.class);
log.info("cat={}", cat);
}
运行结果:
/**
* Parse constructor-arg sub-elements of the given bean element.
*/
public void parseConstructorArgElements(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, CONSTRUCTOR_ARG_ELEMENT)) // 只解析constructor-arg标签
parseConstructorArgElement((Element) node, bd);
}
}
/**
* 解析constructor-arg元素
*/
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE); // "index"
String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE); // "type"
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // "name"
/** 1:如果配置了"index",则执行if内语句 */
if (StringUtils.hasLength(indexAttr)) {
try {
int index = Integer.parseInt(indexAttr);
if (index < 0) error("'index' cannot be lower than 0", ele);
else {
try {
this.parseState.push(new ConstructorArgumentEntry(index));
/** 1-1:解析属性值 */
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));
/** 1-2:判断index是否重复 */
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index))
error("Ambiguous constructor-arg entries for index " + index, ele);
else
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder); // 将index和对应的"具体值"保存到bd中
}
finally {
this.parseState.pop();
}
}
}
catch (NumberFormatException ex) {
error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
}
/** 2:如果没有为constructor配置"index"属性,则执行else这部分 */
else {
try {
this.parseState.push(new ConstructorArgumentEntry());
/** 2-1:解析属性值 */
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); // 将值保存到BeanDefinition中
}
finally {
this.parseState.pop();
}
}
}
1-1:解析属性值
/**
* 获取属性元素的值。可能是一个列表等等,也用于构造函数的参数
*/
@Nullable
public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
String elementName = (propertyName != null ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element");
/** 1:获得<constructor-arg>标签下的子node列表 */
NodeList nl = ele.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
/** 1-2:不处理"description"元素和"meta"元素 */
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) {
if (subElement != null)
error(elementName + " must not contain more than one sub-element", ele);
else
subElement = (Element) node;
}
}
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); // 是否配置了"ref"属性
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); // 是否配置了"value"属性
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null))
error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
/** 2:针对配置了"ref"属性进行解析操作 */
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE); // 获得"ref"属性值
if (!StringUtils.hasText(refName))
error(elementName + " contains empty 'ref' attribute", ele);
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(ele));
return ref;
}
/** 3:针对配置了"value"属性进行解析操作 */
else if (hasValueAttribute) {
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); // 获得"value"属性值
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
/** 4:针对存在子元素的情况进行解析操作 */
else if (subElement != null) {
return parsePropertySubElement(subElement, bd); // 解析子元素
}
/** 5:都不满足,抛出异常 */
else {
error(elementName + " must specify a ref or value", ele); // 都不满足,抛出异常
return null;
}
}
/** 9:解析property子元素 */
parsePropertyElements(ele, bd);
解析property子元素,返回值使用PropertyValue进行封装,并记录在了BeanDefinition的 propertyValues属性里。
/**
* Parse property sub-elements of the given bean element.
*/
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); // 解析property配置信息
}
}
/**
* 解析属性元素
*/
public void parsePropertyElement(Element ele, BeanDefinition bd) {
String propertyName = ele.getAttribute(NAME_ATTRIBUTE); // 获得"name"属性值
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)) { // 如果发现name属性值重复,则报错
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
Object val = parsePropertyValue(ele, bd, propertyName); // 解析property属性值
PropertyValue pv = new PropertyValue(propertyName, val);
parseMetaElements(ele, pv); // 解析meta属性值
pv.setSource(extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv); // 将property属性值封装到PropertyValue实例对象中,然后保存到BeanDefinition
}
finally {
this.parseState.pop();
}
}
/**
* 获取属性元素的值。可能是一个列表等等,也用于构造函数的参数
*/
@Nullable
public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
String elementName = (propertyName != null ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element");
/** 1:获得<constructor-arg>标签下的子node列表 */
NodeList nl = ele.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
/** 1-2:不处理"description"元素和"meta"元素 */
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) {
if (subElement != null)
error(elementName + " must not contain more than one sub-element", ele);
else
subElement = (Element) node;
}
}
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); // 是否配置了"ref"属性
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); // 是否配置了"value"属性
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null))
error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
/** 2:针对配置了"ref"属性进行解析操作 */
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE); // 获得"ref"属性值
if (!StringUtils.hasText(refName))
error(elementName + " contains empty 'ref' attribute", ele);
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(ele));
return ref;
}
/** 3:针对配置了"value"属性进行解析操作 */
else if (hasValueAttribute) {
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); // 获得"value"属性值
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
/** 4:针对存在子元素的情况进行解析操作 */
else if (subElement != null) {
return parsePropertySubElement(subElement, bd); // 解析子元素
}
/** 5:都不满足,抛出异常 */
else {
error(elementName + " must specify a ref or value", ele); // 都不满足,抛出异常
return null;
}
}
/** 10:解析qualifier子元素 */
parseQualifierElements(ele, bd);
进行匹配操作,没有指定bean名称的时候,比如使用类型去匹配的时候。
当同一类型的bean注入到 IOC 之后, Spring容器中匹配的候选Bean数目必须 有且仅有一个,那么此时,我们可以通过Qualifier指出注入Bean的名称,这样歧义就消除掉了。
由于@Autowired是根据类型进行匹配 的,所以可以搭配@Qualifier实现针对名称进行匹配
/**
* Parse qualifier sub-elements of the given bean element.
*/
public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) // "qualifier"
parseQualifierElement((Element) node, bd);
}
}
/**
* 解析qualifier元素
*/
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
String typeName = ele.getAttribute(TYPE_ATTRIBUTE); // 获得"type"属性值
if (!StringUtils.hasLength(typeName)) {
error("Tag 'qualifier' must have a 'type' attribute", ele);
return;
}
this.parseState.push(new QualifierEntry(typeName));
try {
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
qualifier.setSource(extractSource(ele));
String value = ele.getAttribute(VALUE_ATTRIBUTE); // 获得"value"属性值
if (StringUtils.hasLength(value))
qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
// 获得qualifier下所有的子节点列表
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) { // "attribute"
Element attributeEle = (Element) node;
String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE); // "key"
String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE); // "value"
if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
attribute.setSource(extractSource(attributeEle));
qualifier.addMetadataAttribute(attribute);
}
else {
// 如果使用了attribute标签,则必须包含name和value属性值
error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
return;
}
}
}
bd.addQualifier(qualifier); // 将qualifier配置信息保存到AutowireCandidateQualifier实例对象中,并将其保存到BeanDefinition中
}
finally {
this.parseState.pop();
}
}
回到 : /** 4: 解析配置文件中其它的属性,并封装为GenericBeanDefinition实例 */
/** 4: 解析配置文件中其它的属性,并封装为GenericBeanDefinition实例 */
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) { // eg1:beanName="m416"
try {
if (containingBean != null)
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases); // eg1:aliases.size()=0
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); // eg1:beanName="m416",aliasesArray=[]
}
return null;
以上代码的含义:如果beanName为空,就去解析beanName
回到:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// step1:元素解析
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// step2:如果子节点下还有自定义标签,则对其进行解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// step3:对bdHoldr进行注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
BeanDefinitionStoreException ex = var5;
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
}
// step4:发送注册事件
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
当Spring中标签的子元素使用了自定义标签配置,则会被该方法解析,如下所示:
step2:如果子节点下还有自定义标签,则对其进行解析
decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef)
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
return this.decorateBeanDefinitionIfRequired(ele, originalDef, (BeanDefinition)null);
}
// 如果适用的话,通过命名空间处理程序装饰给定的bean定义
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = originalDef;
NamedNodeMap attributes = ele.getAttributes();
// 首先根据自定义属性进行装饰
// eg1: attribtes=[autowire="default",
// autowire-candidate="default",
// class="com.muse.springdemo.entiry.Gun",
// id="m416",
// lazy-init="default"]
for(int i = 0; i < attributes.getLength(); ++i) {
Node node = attributes.item(i);
finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
}
// 基于自定义嵌套元素进行装饰。
NodeList children = ele.getChildNodes();
for(int i = 0; i < children.getLength(); ++i) {
Node node = children.item(i);
if (node.getNodeType() == 1) {
finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
无论是对所有属性还是所有子节点的解析,都会执行decorateIfRequired方法, 其中,isDefaultNamespace(namespaceUri)是通过判断namespaceUri不为空,并且等于 "http://www.springframework.org/schema/beans",如果都满足,则是默认的命名空间。 否则是自定义的命名空间。
public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
String namespaceUri = this.getNamespaceURI(node); // 获得自定义标签的命名空间
// 只针对【自定义标签】进行解析
if (namespaceUri != null && !this.isDefaultNamespace(namespaceUri)) {
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); // 根据命名空间找到对应的处理器
if (handler != null) {
BeanDefinitionHolder decorated = handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); // 执行修饰操作
if (decorated != null) {
return decorated;
}
} else if (namespaceUri.startsWith("http://www.springframework.org/schema/")) {
this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
}
}
return originalDef;
}
(以下先忽略)
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
Map<String, Object> handlerMappings = this.getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
} else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler)handlerOrClassName;
} else {
String className = (String)handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
} else {
NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
} catch (ClassNotFoundException var7) {
ClassNotFoundException ex = var7;
throw new FatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex);
} catch (LinkageError var8) {
LinkageError err = var8;
throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err);
}
}
}
step4:发送注册事件(默认没有任何实现)
// 触发一个组件注册事件
public void fireComponentRegistered(ComponentDefinition componentDefinition) {
this.eventListener.componentRegistered(componentDefinition);
}
step3:对bdHoldr进行注册
在下面的代码中,我们可以看到总共有两个步骤的操作,分别是:
① 注册beanName和BeanDefinition
② 注册beanName和alias别名
** 注册 beanName 和 BeanDefinition
从方法registerBeanDefinition的代码中,我们可以看到针对bean的注册处理方式上,主 要进行了以下几个步骤:
① 对AbstractBeanDefinition的校验。在解析XML文件的时候我们提过校验,但是此 校验非彼校验,之前的校验是针对XML格式的校验,而此时的校验是针对于 AbstractBeanDefinition的methodOverrides属性和factoryMethodName的。
② 对beanName已经注册的情况的处理。如果设置了不允许bean的覆盖,则需要抛出 异常,否则直接覆盖。
③ 加入beanDefinitionMap缓存,更新beanName和BeanDefinition。
④ 清除解析之前留下的对应beanName的缓存
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// 获得beanName,注册beanName和beanDefiniton
String beanName = definitionHolder.getBeanName(); // eg1: beanName="m416"
// eg1: DefaultListableBeanFactory#registerBeanDefinition(…)
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 获得别名alias(如果有的话),注册bean的别名
String[] aliases = definitionHolder.getAliases(); // eg1: aliases=[]
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias); // SimpleAliasRegisstry#registerAlias
}
}
}
注册beanName:
registerBeanDefinition():
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
// eg1:beanName="m416" beanDefinition=GenericBeanDefinition@2236
@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");
/** 1:针对于methodOverrides属性的校验 */
if (beanDefinition instanceof AbstractBeanDefinition) { // eg1:true
try {
((AbstractBeanDefinition) beanDefinition).validate(); // 校验操作,不满足则抛出异常
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex);
}
}
/** 2-1:对beanName已经注册情况的处理。如果设置了不允许bean的覆盖,则需要抛出异常,否则直接覆盖 */
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); // eg1:beanDefinitionMap.size()=0
if (existingDefinition != null) { // eg1:existingDefinition=null
if (!isAllowBeanDefinitionOverriding())
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
this.beanDefinitionMap.put(beanName, beanDefinition); // 更新beanName和BeanDefinition
}
/** 2-2:如果这个bean之前没有加载过,加入beanDefinitionMap缓存,更新beanName和BeanDefinition */
else {
// 如果bean已经开始被创建,则需要加锁处理
if (hasBeanCreationStarted()) { // eg1:false
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition); // 更新beanName和BeanDefinition
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
this.beanDefinitionMap.put(beanName, beanDefinition); // 更新beanName和BeanDefinition
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
/** 3:清除解析之前留下的对应beanName的缓存 */
if (existingDefinition != null || containsSingleton(beanName)) // eg1:false
resetBeanDefinition(beanName);
else if (isConfigurationFrozen()) // eg1:false
clearByTypeCache();
}
/** 1:针对于methodOverrides属性的校验 */
((AbstractBeanDefinition) beanDefinition).validate(); 的validate():
// 校验bean definition,不满足抛异常
public void validate() throws BeanDefinitionValidationException {
// 存在(lookup-method或者replace-method属性)并且还存在factory-method属性,则不满足校验,直接抛出异常
if (this.hasMethodOverrides() && this.getFactoryMethodName() != null) {
throw new BeanDefinitionValidationException("Cannot combine factory method with container-generated method overrides: the factory method must create the concrete bean instance.");
} else {
if (this.hasBeanClass()) { // eg1: 在bean创建成功的时候才有beanClass,当下还没有把配置加载完,所以返回false
this.prepareMethodOverrides();
}
}
}
// 返回该定义是否指定bean类
public boolean hasBeanClass() {
// eg1: beanClass="com.muse.springdemo.entiry.Gun"
return this.beanClass instanceof Class; // eg1: false
}
// 验证并准备为该bean定义的方法覆盖,检查是否存在指定名称的方法
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// 检查查找方法是否存在,并确定他们的重载状态
if (this.hasMethodOverrides()) {
this.getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
// 验证并准备给定的方法覆盖,检查指定名称的方法是否存在,如果没有找到,则将其标记为重载
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
// 获得指定类中某个方法名称被定义的方法个数
int count = ClassUtils.getMethodCountForName(this.getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException("Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + this.getBeanClassName() + "]");
} else {
if (count == 1) {
mo.setOverloaded(false); // 将重写标记为未重载
}
}
}
注册bean的别名:
举例:
<!-- alias 标签演示 -->
<bean id="ent" class="com.muse.springdemo.alias.Entitlement">
<property name="name" value="Entitlement"/>
<property name="time" value="50"/>
</bean>
<alias name="ent" alias="alias_ent"/>
SimpleAliasRegisstry#registerAlias
对alias标签的解析分为两部分:
第一部分:
注册别名Alias的方法registry.registerAlias(beanName, alias)处理逻辑:
① 若alias与beanName的值相同,则从aliasMap中移除原有alias。
② 否则,如果之前已经建立过name和alias的映射了,则直接返回即可。
③ alias循环检查,即:当A——>B存在时,若再出现B——>A,则会抛出异常。
④ 注册alias和beanName到aliasMap中。
// eg1:name="ent", alias="alias_ent"
@Override
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) { // eg1:aliasMap.size()=0
/** 1-1:如果name和alias名称相同,则移除别名alias映射 */
if (alias.equals(name)) // eg1:false
this.aliasMap.remove(alias);
/** 1-2:如果之前已经建立过name和alias的映射了,则直接返回即可 */
else {
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) { // eg1:registeredName=null
if (registeredName.equals(name))
return;
if (!allowAliasOverriding())
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
/** 1-2-1:alias循环检查,当A——>B存在时,若再出现B——>A,则会抛出异常 */
checkForAliasCircle(name, alias); // eg1:DefaultListableBeanFactory#checkForAliasCircle(name, alias)
/** 1-2-2:维护alias与name之间的关系 */
this.aliasMap.put(alias, name);
}
}
}
以及:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
/** 1:针对<import>标签进行解析 */
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT))
importBeanDefinitionResource(ele);
/** 2:针对<alias>标签进行解析 */
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT))
processAliasRegistration(ele);
/** 3:针对<bean>标签进行解析 */
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT))
processBeanDefinition(ele, delegate);
/** 4:针对<beans>标签进行解析 */
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT))
doRegisterBeanDefinitions(ele);
}
第一部分:
/**
* 检查给定的名称是否已经作为另一个方向的别名指向了给定的别名,提前捕获循环引用并抛出相应的IllegalStateException。
*/
// eg1:name="ent", alias="alias_ent"
protected void checkForAliasCircle(String name, String alias) {
if (hasAlias(alias, name)) { // eg1:false
throw new IllegalStateException("Cannot register alias '" + alias +
"' for name '" + name + "': Circular reference - '" +
name + "' is a direct or indirect alias for '" + alias + "' already");
}
}
/**
* 确定给定的名称是否注册了给定的别名。
*/
// eg1:name="ent", alias="alias_ent"
public boolean hasAlias(String name, String alias) {
String registeredName = this.aliasMap.get(alias); // eg1: aliasMap.size()=0,registeredName=null
return ObjectUtils.nullSafeEquals(registeredName, name) || // eg1:false
(registeredName != null // eg1:false
&& hasAlias(name, registeredName));
}
第二部分:
在对bean进行定义时,除了使用id属性来指定名称之外,为了提供多个bean的名称,我 们可以使用alias标签来指定。例如,通过在标签中设置name属性来为bean设置 别名(alias)。如下所示:
<bean id="gun" name="m416, ak47" class="com.muse.Gun" />
另外,Spring还有另外一种声明别名的方式:
<bean id="gun" class="com.muse.Gun" />
<alias name="gun" alias="m416, ak47"/>
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
/** 2:针对<alias>标签进行解析 */
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT))
processAliasRegistration(ele);
}
/**
* 处理给定的alias元素,用注册表注册别名。
*/
protected void processAliasRegistration(Element ele) {
/** 1:配置的name和alias必须都存在,否则输出异常 */
String name = ele.getAttribute(NAME_ATTRIBUTE); // eg1:name="ent"
String alias = ele.getAttribute(ALIAS_ATTRIBUTE); // eg1:alias="alias_ent"
boolean valid = true;
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele); // name不能为空
valid = false;
}
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele); // alias不能为空
valid = false;
}
/** 2:执行name和alias的注册操作 */
if (valid) {
try {
// eg1:name="ent", alias="alias_ent", SimpleAliasRegistry#registerAlias(name, alias)
getReaderContext().getRegistry().registerAlias(name, alias);
}
catch (Exception ex) {
getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, ex);
}
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}
registerAlias(name, alias):跟上面的部分1相同。
import标签:
对于项目中的大量Spring配置文件而言,如果我们采取分模块维护,那么更易于我们的管 理。我们可以通过采用标签,来引入不同模块的配置文件,具体如下所示:
<beans>
<import resource="order.xml" />
<import resource="stock.xml" />
</beans>
import标签的解析逻辑:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
/** 1:针对<import>标签进行解析 */
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT))
importBeanDefinitionResource(ele);
}
}
/**
* 解析“import”元素,并将给定资源中的bean定义加载到bean工厂中。 <import resource="order.xml"/>
*/
protected void importBeanDefinitionResource(Element ele) {
/** 1:解析resource属性,如果没配置,则抛出异常 */
String location = ele.getAttribute(RESOURCE_ATTRIBUTE); // "resource"
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
/** 2:查看位置是绝对地址还是相对地址 */
// Resolve system properties: e.g. "${user.dir}"
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<>(4);
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {}
/** 3-1:如果是绝对路径,则直接根据地址加载对应的配置文件 */
if (absoluteLocation) {
try {
getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
/** 3-2:如果是相对路径 */
else {
try {
/** 3-2-1:优先使用Resource子类(VfsResource、FileSystemResource……)的方法尝试执行解析操作 */
Resource relativeResource = getReaderContext().getResource().createRelative(location);
if (relativeResource.exists()) {
getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
/** 3-2-2:如果解析不成功,则将给定的相对路径应用于给定的Java资源路径进行解析 */
else {
String baseLocation = getReaderContext().getResource().getURL().toString();
getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, ex);
}
}
/** 4:解析后进行监听器激活处理 */
Resource[] actResArray = actualResources.toArray(new Resource[0]);
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
// eg1: text = "bean.xml"
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
// strictHelper = null
if (this.strictHelper == null) {
this.strictHelper = this.createPlaceholderHelper(false);
}
return this.doResolvePlaceholders(text, this.strictHelper);
}
// eg1: text = "bean.xml"
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
// placeholderPrefix = "${", placeholderSuffix = "}", valueSeparator = ":"
return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix, this.valueSeparator, ignoreUnresolvablePlaceholders);
}
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
return helper.replacePlaceholders(text, this::getPropertyAsRawString);
}
beans标签:递归调用bean解析的过程。
location --> resource --> document --> beanDefinition --> -->