本系列文章:
之前的流程建议大家看一下01篇
这里一句话简单概括一下01篇的流程: 定位xml文件资源,包装为Resource对象—>xml文件被解析为一颗DOM树,即Document对象—>BeanDefinitionDocumentReader负责对Document对象进行解析—>BeanDefinitionDocumentReader内部又把解析Document对象的事情委托给了BeanDefinitionParserDelegate来完成
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//对imprt标签进行处理
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)) {
doRegisterBeanDefinitions(ele);
}
}
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//委托BeanDefinitionParserDelegate来对bean标签进行解析
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//对自定义子标签再进行处理---如果存在的话
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//注册BeanDefinition
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));
}
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
//这里的ele是bean标签
return parseBeanDefinitionElement(ele, null);
}
目标方法:
/**
* Parses the supplied <bean> element. May return null
* if there were errors during parse. Errors are reported to the
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//解析id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//解析name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//存放bean的别名的集合
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
//分割name属性---得到的是别名数组
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
//加入别名集合
aliases.addAll(Arrays.asList(nameArr));
}
//id规定了beanName
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
//beanName为空,就把别名数组中第一个元素拿出来作为beanName
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
//别名不能重复
checkNameUniqueness(beanName, aliases, ele);
}
/
//传入bean标签,beanName,containingBean开始正式对bean标签进行解析得到beanDefinition
//返回的beanDefinition类型是GenericBeanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
///
if (beanDefinition != null) {
//beanName为空---没给id,别名也没有该咋办?
if (!StringUtils.hasText(beanName)) {
try {
//containingBean不为空
if (containingBean != null)
{
//自动生成一个beanName
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
//如果containingBean为空,那就通过下面的方式生成一个beanName
//这里获得的beanName是全类名加上一个#0---->org.deepSpring.Bean#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)) {
aliases.add(beanClassName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
//得到别名数组
String[] aliasesArray = StringUtils.toStringArray(aliases);
//生成BeanDefinitionHolder----这个类干的事情就是整合了beanDefinition,beanName和aliasesArray
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
记住该类BeanDefinitionParserDelegate才是被委托解析xml生成BeanDefinition的对象
/**
* Parse the bean definition itself, without regard to name or aliases. May return
null if problems occurred during the parsing of the bean definition.
*/
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
//跟踪解析的状态
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
//获取bean标签里面的className属性
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
//获取bean标签里面的parent属性
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//生成BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//硬编码解析默认bean的各种属性---因为BeanDefinition里面成员属性和bean标签里面能写的属性一一映射
//这样的话,每解析出一个属性,就直接设置BeanDefinition对应映射到的值即可
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//提取description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析元数据
parseMetaElements(ele, bd);
//解析lookup-method属性
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析replace-method属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造函数参数
parseConstructorArgElements(ele, bd);
//解析property子元素
parsePropertyElements(ele, bd);
//解析qualifier子元素
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
throws ClassNotFoundException {
//BeanDefinitionReaderUtils来创建BeanDefinition
//这个工具类还可以用来生成beanName,注册BeanDefinition上面都讲到过了
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
BeanDefinitionReaderUtils类:
public static AbstractBeanDefinition createBeanDefinition(
@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
//创建的是GenericBeanDefinition
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else {
bd.setBeanClassName(className);
}
}
return bd;
}
下面我们开始对bean标签里面的属性进行解析了
/**
* Apply the attributes of the given bean element to the given bean * definition.
* @param ele bean declaration element
* @param beanName bean name
* @param containingBean containing bean definition
* @return a bean definition initialized according to the bean element attributes
*/
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
//解析scope属性
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}
else if (containingBean != null) {
//如果是内嵌的beanDefinition情况下,没有单独指定scope属性,则使用父类的默认属性
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
}
//解析abstract属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
//解析lazy-init属性
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (isDefaultValue(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
//如果没有数组,或设置成其他字符都会被设置成false---即默认都不是懒惰初始化的
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
//解析autowire属性
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
//设置自动注入模式--构造器注入,按照类型注入等
bd.setAutowireMode(getAutowireMode(autowire));
//解析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 (isDefaultValue(autowireCandidate)) {
String candidatePattern = this.defaults.getAutowireCandidates();
if (candidatePattern != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
}
else {
bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
}
//解析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);
bd.setInitMethodName(initMethodName);
}
else if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
//解析destory-method属性
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
bd.setDestroyMethodName(destroyMethodName);
}
else if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
//解析factory-method属性
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
//解析factory-bean属性
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
解析完bean标签上面可以标注的所有属性后,下面开始解析bean标签内部可以使用过的子标签,从< meta >标签开始
<bean name="dhy,xpy" id="myTestBean" class="org.deepSpring.Bean">
<meta key="dhy" value="xpy"/>
</bean>
//这里的ele是bean标签,BeanMetadataAttributeAccessor 是AbstractBeanDefinition,上面讲过AbstractBeanDefinition继承了该类
//该类是用来统一管理元数据信息的类
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
// 获取当前节点的所以子元素
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//提取meta
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
Element metaElement = (Element) node;
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
//BeanMetadataAttribute对元数据的key,value进行封装
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(extractSource(metaElement));
//加入MetadataAttribute集合中
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
我打赌很多人可能都不知道这个属性干啥用的,下面我简单通过一个例子介绍一下:
public abstract class Test {
public void Show()
{
getPeo().Show();
}
public abstract Peo getPeo();
}
public class Peo {
public void Show()
{
System.out.println("我是人");
}
}
如果我们想让Test对象被代理,然后其getPeo方法由代理对象实现,返回一个Peo类型的bean,可以通过lookup-method属性完成,当前注解直接标注在getPeo方法上也可以,这里不进行演示了:
<bean id="Test" class="org.deepSpring.Test">
<lookup-method name="getPeo" bean="Peo"></lookup-method>
</bean>
<bean id="Peo" class="org.deepSpring.Peo"></bean>
测试:
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml"));
Test bean = beanFactory.getBean(Test.class);
bean.Show();
下面让我们走进parseLookupOverrideSubElements的方法
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
/**
* Parse lookup-override sub-elements of the given bean element.
* beanEle是bean标签,MethodOverrides 是BeanDefintion里面存放这种需要被重写的方法集合
*/
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//当前bean的子元素为LOOKUP_METHOD---其实大家可以发现,对一个属性进行解析的流程是类似的
if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
Element ele = (Element) node;
//获取要修饰的方法
String methodName = ele.getAttribute(NAME_ATTRIBUTE);
//获取要配置返回的bean
String beanRef = ele.getAttribute(BEAN_ELEMENT);
//LookupOverride对上面两个属性进行封装---这个步骤和对元数据的封装思想一致
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(extractSource(ele));
//加入需要被覆盖的方法集合
overrides.addOverride(override);
}
}
}
还是举个小例子吧:
public class Peo {
public void Show()
{
System.out.println("我是人");
}
}
如果我们要在运行期间替换掉Peo的show方法,或者对其进行方法增强该怎么办呢? —AOP,不不不,后面再聊,我们现在可以用MethodReplacer 办到:
public class MyReplacer implements MethodReplacer {
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("replace method");
return null;
}
}
配置文件:
<bean id="Peo" class="org.deepSpring.Peo">
<replaced-method name="Show" replacer="MyReplacer"></replaced-method>
</bean>
<bean id="MyReplacer" class="org.deepSpring.MyReplacer"></bean>
测试类:
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml"));
Peo bean = beanFactory.getBean(Peo.class);
bean.Show();
非常类似动态代理,懂得都懂,不懂我也就不多说了
回到replace-method方法进行解析的地方:
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
对应方法源码:
/**
* Parse replaced-method sub-elements of the given bean element.
*/
public void parseReplacedMethodSubElements(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, REPLACED_METHOD_ELEMENT)) {
//拿到<replaced-method>该标签
Element replacedMethodEle = (Element) node;
//方法名
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
//replacer
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
//ReplaceOverride进行封装
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
// Look for arg-type match elements.
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
for (Element argTypeEle : argTypeEles) {
//记录参数
String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(extractSource(replacedMethodEle));
//这里还是添加进overrides集合
overrides.addOverride(replaceOverride);
}
}
}
<bean id="peo" class="org.deepSpring.Peo">
<!--默认情况下是按照参数的顺序注入,当指定index索引后就可以改变注入参数的顺序 -->
<constructor-arg index="0">
<value>大忽悠</value>
</constructor-arg>
<constructor-arg index="1">
<value>18</value>
</constructor-arg>
</bean>
parseConstructorArgElements(ele, bd);
方法对应源码:
/**
* 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);
//只解析<constructor-arg>标签
if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
//这里之所以将解析逻辑放到其他方法中进行实现,是因为构造函数逻辑处理比较复杂
parseConstructorArgElement((Element) node, bd);
}
}
}
/**
* Parse a constructor-arg element.
* 这里传入的Element 标签是constructor-arg
*/
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
//提取Index,type,name属性
String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//如果设置了index属性---即规定了当前构造参数对应的索引----按照index指定位置进行注入
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));
//constructor-arg标签对应的值进行解析
Object value = parsePropertyValue(ele, bd, null);
//通过一个ValueHolder来构造函数参数对应的值
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
//尝试去设置type和name属性
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));
//条件成立,说明存在两个以上的constructor-arg标签的index有重复,显然这不合理
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
error("Ambiguous constructor-arg entries for index " + index, ele);
}
else {
//否则添加进集合----参数索引和该位置索引处构造参数的值,该映射关系保存在indexedArgumentValues集合中
//indexedArgumentValues是一个map集合
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
}
}
finally {
this.parseState.pop();
}
}
}
catch (NumberFormatException ex) {
error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
}
else {
//没有设置index属性---按照参数的顺序注入
try {
//追踪解析状态--这里大家不要纠结,前期不是重点
this.parseState.push(new ConstructorArgumentEntry());
//constructor-arg标签对应的值进行解析
Object value = parsePropertyValue(ele, bd, null);
//ValueHolder封装当前索引处对应的参数值
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
//尝试去设置type和name
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));
//这里就默认按照参数的顺序注入----这里参数保存的位置是在genericArgumentValues
//genericArgumentValues是一个list集合
bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
}
finally {
this.parseState.pop();
}
}
}
<constructor-arg index="0">
//该方法解析此处的标签内容,显然这里只能写value,list,或者ref标签
//解析后,返回该标签内部的值
<value>大忽悠</value>
</constructor-arg>
还可以这样写
<constructor-arg index="1" value="张三"></constructor-arg>
<constructor-arg index="0" ref="bean1"></constructor-arg>
/**
* Get the value of a property element. May be a list etc.
* Also used for constructor arguments, "propertyName" being null in this case.
* 因为<constructor-arg>没有<constructor-arg name="xxx">的用法,
* 但是<property name="name">是有的,因此要注意
*/
@Nullable
public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
String elementName = (propertyName != null ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element");
//一种属性只能对应一种类型ref, value, list.
// Should only have one child element: ref, value, list, etc.
NodeList nl = ele.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//对DESCRIPTION_ELEMENT和META_ELEMENT不进行解析
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
!nodeNameEquals(node, META_ELEMENT)) {
//这里为啥要判断,很简单,因为一个<constructor-arg>标签下最多只能有一个value标签吧,你搞两个出来,这不合适吧
// Child element is what we're looking for.
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {
//拿到<constructor-arg>下面的子标签
subElement = (Element) node;
}
}
}
//尝试去获取该ele这里是construct-arg标签的ref属性和value属性
//注意这里不是subElement 子标签
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
//子标签上不能同时有ref和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);
}
//如果construct-arg标签上有ref属性
if (hasRefAttribute) {
//拿到ref指向的refName
String refName = ele.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
//RuntimeBeanReference封装引用类型
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(ele));
//直接返回
return ref;
}
//如果construct-arg标签上有value属性
else if (hasValueAttribute) {
//用TypedStringValue 封装值类型
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
valueHolder.setSource(extractSource(ele));
//直接返回
return valueHolder;
}
//没有上面两个属性,就只能判断具体是哪个子标签,然后进行解析
else if (subElement != null) {
//传入子元素进行解析---该方法是个通用方法
return parsePropertySubElement(subElement, bd);
}
else {
// Neither child element nor "ref" or "value" attribute found.
error(elementName + " must specify a ref or value", ele);
return null;
}
}
/**
* Parse a value, ref or collection sub-element of a property or
* constructor-arg element.
* @param ele subelement of property element; we don't know which yet
* @param bd the current bean definition (if any)
*/
@Nullable //这里的ele就是对应需要解析的子标签了
public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
return parsePropertySubElement(ele, bd, null);
}
/**
* Parse a value, ref or collection sub-element of a property or
* constructor-arg element.
* @param ele subelement of property element; we don't know which yet
* @param bd the current bean definition (if any)
* @param defaultValueType the default type (class name) for any
* {@code <value>} tag that might be created
*/
@Nullable
public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
//因为子标签可能是用户自定义的,因此需要判断一下
if (!isDefaultNamespace(ele)) {
//调用用户自定义实现的接口进行解析
return parseNestedCustomElement(ele, bd);
}
//子标签是bean类型标签
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
//如何解析bean标签----parseBeanDefinitionElement大家可以翻到上面梦开始的地方,我们现在还在梦中,快要醒了
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
//解析出来BeanDefinitionHolder ,然后返回
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;
//如果refName没找到
if (!StringUtils.hasLength(refName)) {
// A reference to the id of another bean in a parent context.
//可能是继承了parent标签的内容,去找parent属性
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean' 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进行包装,然后返回
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
ref.setSource(extractSource(ele));
return ref;
}
//是idref类型的子标签
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
return parseIdRefElement(ele);
}
//是value类型的子标签
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultValueType);
}
//NULL类型子标签
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
// It's a distinguished null value. Let's wrap it in a TypedStringValue
// object in order to preserve the source location.
TypedStringValue nullHolder = new TypedStringValue(null);
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
//array类型
else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
//list类型
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd);
}
//set类型
else if (nodeNameEquals(ele, SET_ELEMENT)) {
return parseSetElement(ele, bd);
}
//map类型
else if (nodeNameEquals(ele, MAP_ELEMENT)) {
return parseMapElement(ele, bd);
}
//props类型
else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
return parsePropsElement(ele);
}
//未知标签
else {
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
parsePropertyElements(ele, bd);
方法源码:
/**
* 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方法进行解析
parsePropertyElement((Element) node, bd);
}
}
}
public void parsePropertyElement(Element ele, BeanDefinition bd) {
//提取name属性
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
//追踪解析状态
this.parseState.push(new PropertyEntry(propertyName));
try {
//name属性不能重复呀!!!
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
//传入prorperty标签和对应标注的name,得到property里面的值---
//这个函数就是上面构造参数解析得到<construct-agr>标签里面值的时候用到的函数,不清楚的回看上面的讲解
//propertyName只是用来做错误日志记录的,没别的用,因此解析过程和构造参数一模一样
Object val = parsePropertyValue(ele, bd, propertyName);
//PropertyValue进行封装---其实大概思路都这样,针对不同的标签,用一个类对得到的结果进行封装
PropertyValue pv = new PropertyValue(propertyName, val);
//解析元数据标签
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
//加入BeanDefinition的PropertyValue集合
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
/**
* 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)) {
parseQualifierElement((Element) node, bd);
}
}
}
/**
* Parse a qualifier element.
*/
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
//获取到type值
String typeName = ele.getAttribute(TYPE_ATTRIBUTE);
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));
//获取value
String value = ele.getAttribute(VALUE_ATTRIBUTE);
if (StringUtils.hasLength(value)) {
qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
}
//下面可能还有子标签
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//qualifer标签下面是否有attribute标签
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
Element attributeEle = (Element) node;
String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
attribute.setSource(extractSource(attributeEle));
qualifier.addMetadataAttribute(attribute);
}
else {
error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
return;
}
}
}
//添加到beanDefinition的qualifiers集合中
bd.addQualifier(qualifier);
}
finally {
this.parseState.pop();
}
}
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
/**
* 默认bean的作用域范围
*/
public static final String SCOPE_DEFAULT = "";
/**
* 自动注入模式---不进行注入
*/
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
/**
* 按照名字进行注入
*/
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
/**
* 按照类型进行注入
*/
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
/**
* 通过构造函数参数进行注入
*/
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
/**
* 自动判断如何进行注入
*/
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
/**
* Constant that indicates no dependency check at all.
*/
public static final int DEPENDENCY_CHECK_NONE = 0;
/**
* Constant that indicates dependency checking for object references.
*/
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
/**
* Constant that indicates dependency checking for "simple" properties.
*/
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
/**
* Constant that indicates dependency checking for all properties
*/
public static final int DEPENDENCY_CHECK_ALL = 3;
/**
* Constant that indicates the container should attempt to infer the
* {@link #setDestroyMethodName destroy method name} for a bean as opposed to
* explicit specification of a method name. The value {@value} is specifically
* designed to include characters otherwise illegal in a method name, ensuring
* no possibility of collisions with legitimately named methods having the same
* name.
* <p>Currently, the method names detected during destroy method inference
* are "close" and "shutdown", if present on the specific bean class.
*/
public static final String INFER_METHOD = "(inferred)";
@Nullable //目标对象className
private volatile Object beanClass;
@Nullable//默认作用域范围
private String scope = SCOPE_DEFAULT;
//bean标签可以标注abstract属性--是否抽象
private boolean abstractFlag = false;
@Nullable//是否懒加载
private Boolean lazyInit;
//当前Bean的自动注入模式
private int autowireMode = AUTOWIRE_NO;
//依赖检查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
//一个bean实例化前,需要依赖其他的bean的集合
@Nullable
private String[] dependsOn;
//容器在查找自动装配对象的时候,是否会将该bean作为bean自动装配的候选者
private boolean autowireCandidate = true;
//当存在多个bean的候选者时,将作为首选者
private boolean primary = false;
//用于记录Qualifier
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
//Specify a callback for creating an instance of the bean,
//as an alternative to a declaratively specified factory method.
//If such a callback is set, it will override any other constructor
// or factory method metadata. However, bean property population and
// potential annotation-driven injection will still apply as usual.
@Nullable
private Supplier<?> instanceSupplier;
//是否能够访问非公开的构造器和方法
private boolean nonPublicAccessAllowed = true;
//是否以一种宽松的模式解析构造函数
//如果为false,那么下面的场景会抛出异常
//interface Test1{}
//class Test2 implements Test1{};
//class Main{
//Main(Test1){}; Main(Test2){};
//}
private boolean lenientConstructorResolution = true;
//bean属性的factory-bean
@Nullable
private String factoryBeanName;
//bean属性的factory-method
@Nullable
private String factoryMethodName;
//记录构造函数的属性
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
//普通属性集合
@Nullable
private MutablePropertyValues propertyValues;
//方法重写的持有者----lookup-method和replace-method
private MethodOverrides methodOverrides = new MethodOverrides();
//初始化方法---init-method
@Nullable
private String initMethodName;
//destory-method
@Nullable
private String destroyMethodName;
//是否执行Init-method
private boolean enforceInitMethod = true;
//是否执行destory-method
private boolean enforceDestroyMethod = true;
//是否是用户定义的而不是应用程序本身定义的,创建aop的时候为true
private boolean synthetic = false;
//定义这个bean的应用,APPLICATION:用户,INFRASTRUCTER:完全内部使用,与用户无关
//SUPPORT:某些复杂配置的一部分
private int role = BeanDefinition.ROLE_APPLICATION;
//bean的描述信息
@Nullable
private String description;
//这个bean定义的资源
@Nullable
private Resource resource;
....
}
应该是从BeanDefinitionDocumentReader类的parseBeanDefinitions方法处开始,我们第一次看到了对自定义和默认标签的区分解析,但是这里我要说的不是在此处,因为这里是对根标签层面进行区分的,例如:beans标签
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
我们着眼点先放在beans下一级标签中的自定义标签,那就只能从对bean标签底下的自定义标签找起来了
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//重新来到梦的起点
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
让我们再来回归梦的起点
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//大家不要糊涂了,我们上面一直都是对parseBeanDefinitionElement这一个函数进行分析的
//该函数解析完根标签bean后,会返回一个对应的BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//然后就是下面这行代码-----我们开始分析是否需要对自定义标签进行解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
/**
* Decorate the given bean definition through a namespace handler, if applicable.
* @param ele the current element
* @param originalDef the current bean definition
* @return the decorated bean definition
*/
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
return decorateBeanDefinitionIfRequired(ele, originalDef, null);
}
/**
* Decorate the given bean definition through a namespace handler, if applicable.
* @param ele the current element
* @param originalDef the current bean definition
* @param containingBd the containing bean definition (if any)
* @return the decorated bean definition
*/
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
//上一步解析完自定义标签后返回的BeanDefinitionHolder
BeanDefinitionHolder finalDefinition = originalDef;
// Decorate based on custom attributes first.
//遍历所有属性,查看是否有适用于修饰的属性
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.
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;
}
/**
* Decorate the given bean definition through a namespace handler,
* if applicable.
* @param node the current child node
* @param originalDef the current bean definition
* @param containingBd the containing bean definition (if any)
* @return the decorated bean definition
*/
public BeanDefinitionHolder decorateIfRequired(
Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
//获取自定义标签的命名空间
String namespaceUri = getNamespaceURI(node);
//命名空间不为空,并且不是默认命名空间
if (namespaceUri != null && !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/")) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
}
else {
// A custom namespace, not to be handled by Spring - maybe "xml:...".
if (logger.isDebugEnabled()) {
logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
}
}
}
return originalDef;
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//下面分析这一行代码:
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));
}
}
/**
* Register the given bean definition with the given bean factory.
* @param definitionHolder the bean definition including name and aliases
* @param registry the bean factory to register with
* @throws BeanDefinitionStoreException if registration failed
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
//注册bean的定义
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
//注册bean的别名
registry.registerAlias(beanName, alias);
}
}
}
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
@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");
//类型判断---AbstractBeanDefinition中实现了大部分的功能
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
//这里的校验主要是对于AbstractBeanDefinition属性中的methodOverrides校验,
//校验methodOverrides是否与工厂方法并存或者methodOverrides对于的方法根本不存在
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//尝试从当前beanDefinitionMap中取出当前beanNam对应的beanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
//是否需要覆盖
if (existingDefinition != null) {
//说明当前beanName对应的BeanDefinition 在容器中已经存在了
//是否允许覆盖BeanDefinition
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
//根据角色基本进行判断---主要是进行日志输出,如果发生了高级角色覆盖低级角色放入的BeanDefinition
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
//这两个BeanDefinition 不相同
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//这两个BeanDefinition 相同
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//如果允许覆盖就放入beanDefinitionMap覆盖原有的BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//检查这个工厂的 bean 创建阶段是否已经开始,即在此期间是否有任何 bean 被标记为已创建。
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
//beanDefinitionMap是全局变量,当有多个组合的原子性操作的时候,会存在并发访问的问题
synchronized (this.beanDefinitionMap) {
//放入beanDefinitionMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
//更新已经记录的beanName---beanDefinitionNames
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//从集合中移除这个已经注册过的单例名称---manualSingletonNames
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//containsSingleton(beanName) ===> this.singletonObjects.containsKey(beanName)
if (existingDefinition != null || containsSingleton(beanName)) {
//重置所有beanName对应的缓存
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
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) {
//如果beanName与alias相同的话不记录alias,并删除对应的alias
if (alias.equals(name)) {
this.aliasMap.remove(alias);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
} else {
//判断该别名是否注册过
String registeredName = (String)this.aliasMap.get(alias);
if (registeredName != null) {
//注册过,并且该别名对应的值就是当前beanName,那就不需要再管了
if (registeredName.equals(name)) {
return;
}
//如果当前别名对应的beanName与当前需要注册的beanName不一致,那么判断别名的指向是否可以被覆盖
if (!this.allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'.");
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding alias '" + alias + "' definition for registered name '" + registeredName + "' with new target name '" + name + "'");
}
}
//当A->B存在时,如果再次出现A->C->B时候则会存在异常
this.checkForAliasCircle(name, alias);
//进行注册操作
this.aliasMap.put(alias, name);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
//给注册的监听器发送事件,告知beanDefinition创建完毕
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
这一点是书上没有的,但是因为源码中反复出现,我还是拿出来讲一下吧,毕竟有些东西并不难,但是你不知道的话,就会很懵逼
ReaderContext中的Reader指的是BeanDefinitionReader,即BeanDefinitionReader的上下文环境
public class XmlBeanFactory extends DefaultListableBeanFactory {
//XmlBeanFactory内部有一个XmlBeanDefinitionReader 的实例对象
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
...
}
我们来看一下XmlBeanDefinitionReader :
//XmlBeanDefinitionReader 内部有这样一个属性
private ReaderEventListener eventListener = new EmptyReaderEventListener();
//XmlBeanDefinitionReader类中提供了一个设置eventListener 的方法,如果传入null值,则默认为EmptyReaderEventListener
public void setEventListener(@Nullable ReaderEventListener eventListener) {
this.eventListener = (eventListener != null ? eventListener : new EmptyReaderEventListener());
}
//该方法也用到了eventListener---只不过这回是为了创建XmlReaderContext作为参数传入的
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor, this, getNamespaceHandlerResolver());
}
createReaderContext在下面这个熟悉的方法中被调用,该方法是在将xml解析为Document对象后,创建BeanDefinitionDocumentReader后,调用其registerBeanDefinitions方法时,调用了createReaderContext方法
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
并且在BeanDefinitionDocumentReader内部会通过一个成员变量将作为参数传入的readerContext保存下来,然后后面很多地方都会用到这个上下文环境
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
//保存该环境对象
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
下面就来看看这个上下文环境对象都有啥功能吧:
public class XmlReaderContext extends ReaderContext {
private final XmlBeanDefinitionReader reader;
private final NamespaceHandlerResolver namespaceHandlerResolver;
/**
* Construct a new {@code XmlReaderContext}.
* @param resource the XML bean definition resource
* @param problemReporter the problem reporter in use
* @param eventListener the event listener in use
* @param sourceExtractor the source extractor in use
* @param reader the XML bean definition reader in use
* @param namespaceHandlerResolver the XML namespace resolver
*/
public XmlReaderContext(
Resource resource, ProblemReporter problemReporter,
ReaderEventListener eventListener, SourceExtractor sourceExtractor,
XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {
super(resource, problemReporter, eventListener, sourceExtractor);
this.reader = reader;
this.namespaceHandlerResolver = namespaceHandlerResolver;
}
/**
* Return the XML bean definition reader in use.
*/
public final XmlBeanDefinitionReader getReader() {
return this.reader;
}
/**
* Return the bean definition registry to use.
* @see XmlBeanDefinitionReader#XmlBeanDefinitionReader(BeanDefinitionRegistry)
*/
public final BeanDefinitionRegistry getRegistry() {
return this.reader.getRegistry();
}
/**
* Return the resource loader to use, if any.
* <p>This will be non-null in regular scenarios,
* also allowing access to the resource class loader.
* @see XmlBeanDefinitionReader#setResourceLoader
* @see ResourceLoader#getClassLoader()
*/
@Nullable
public final ResourceLoader getResourceLoader() {
return this.reader.getResourceLoader();
}
/**
* Return the bean class loader to use, if any.
* <p>Note that this will be null in regular scenarios,
* as an indication to lazily resolve bean classes.
* @see XmlBeanDefinitionReader#setBeanClassLoader
*/
@Nullable
public final ClassLoader getBeanClassLoader() {
return this.reader.getBeanClassLoader();
}
/**
* Return the environment to use.
* @see XmlBeanDefinitionReader#setEnvironment
*/
public final Environment getEnvironment() {
return this.reader.getEnvironment();
}
/**
* Return the namespace resolver.
* @see XmlBeanDefinitionReader#setNamespaceHandlerResolver
*/
public final NamespaceHandlerResolver getNamespaceHandlerResolver() {
return this.namespaceHandlerResolver;
}
// Convenience methods to delegate to
/**
* Call the bean name generator for the given bean definition.
* @see XmlBeanDefinitionReader#getBeanNameGenerator()
* @see org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName
*/
public String generateBeanName(BeanDefinition beanDefinition) {
return this.reader.getBeanNameGenerator().generateBeanName(beanDefinition, getRegistry());
}
/**
* Call the bean name generator for the given bean definition
* and register the bean definition under the generated name.
* @see XmlBeanDefinitionReader#getBeanNameGenerator()
* @see org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName
* @see BeanDefinitionRegistry#registerBeanDefinition
*/
public String registerWithGeneratedName(BeanDefinition beanDefinition) {
String generatedName = generateBeanName(beanDefinition);
getRegistry().registerBeanDefinition(generatedName, beanDefinition);
return generatedName;
}
/**
* Read an XML document from the given String.
* @see #getReader()
*/
public Document readDocumentFromString(String documentContent) {
InputSource is = new InputSource(new StringReader(documentContent));
try {
return this.reader.doLoadDocument(is, getResource());
}
catch (Exception ex) {
throw new BeanDefinitionStoreException("Failed to read XML document", ex);
}
}
}
XmlReaderContext主要就是保存了XmlBeanDefinitionReader和一个NamespaceHandlerResolver
这里我主要是想讲一下这个事件监听机制,所以来看一下其父类ReaderContext
public class ReaderContext {
private final Resource resource;
private final ProblemReporter problemReporter;
//最多只有一个监听者
private final ReaderEventListener eventListener;
private final SourceExtractor sourceExtractor;
/**
* Construct a new {@code ReaderContext}.
* @param resource the XML bean definition resource
* @param problemReporter the problem reporter in use
* @param eventListener the event listener in use
* @param sourceExtractor the source extractor in use
*/
public ReaderContext(Resource resource, ProblemReporter problemReporter,
ReaderEventListener eventListener, SourceExtractor sourceExtractor) {
this.resource = resource;
this.problemReporter = problemReporter;
this.eventListener = eventListener;
this.sourceExtractor = sourceExtractor;
}
public final Resource getResource() {
return this.resource;
}
// Errors and warnings
/**
* Raise a fatal error.
*/
public void fatal(String message, @Nullable Object source) {
fatal(message, source, null, null);
}
/**
* Raise a fatal error.
*/
public void fatal(String message, @Nullable Object source, @Nullable Throwable cause) {
fatal(message, source, null, cause);
}
/**
* Raise a fatal error.
*/
public void fatal(String message, @Nullable Object source, @Nullable ParseState parseState) {
fatal(message, source, parseState, null);
}
/**
* Raise a fatal error.
*/
public void fatal(String message, @Nullable Object source, @Nullable ParseState parseState, @Nullable Throwable cause) {
Location location = new Location(getResource(), source);
this.problemReporter.fatal(new Problem(message, location, parseState, cause));
}
/**
* Raise a regular error.
*/
public void error(String message, @Nullable Object source) {
error(message, source, null, null);
}
/**
* Raise a regular error.
*/
public void error(String message, @Nullable Object source, @Nullable Throwable cause) {
error(message, source, null, cause);
}
/**
* Raise a regular error.
*/
public void error(String message, @Nullable Object source, @Nullable ParseState parseState) {
error(message, source, parseState, null);
}
/**
* Raise a regular error.
*/
public void error(String message, @Nullable Object source, @Nullable ParseState parseState, @Nullable Throwable cause) {
Location location = new Location(getResource(), source);
this.problemReporter.error(new Problem(message, location, parseState, cause));
}
/**
* Raise a non-critical warning.
*/
public void warning(String message, @Nullable Object source) {
warning(message, source, null, null);
}
/**
* Raise a non-critical warning.
*/
public void warning(String message, @Nullable Object source, @Nullable Throwable cause) {
warning(message, source, null, cause);
}
/**
* Raise a non-critical warning.
*/
public void warning(String message, @Nullable Object source, @Nullable ParseState parseState) {
warning(message, source, parseState, null);
}
/**
* Raise a non-critical warning.
*/
public void warning(String message, @Nullable Object source, @Nullable ParseState parseState, @Nullable Throwable cause) {
Location location = new Location(getResource(), source);
this.problemReporter.warning(new Problem(message, location, parseState, cause));
}
// Explicit parse events
/**
* Fire a defaults-registered event.
*/
public void fireDefaultsRegistered(DefaultsDefinition defaultsDefinition) {
this.eventListener.defaultsRegistered(defaultsDefinition);
}
/**
* Fire a component-registered event.
*/
public void fireComponentRegistered(ComponentDefinition componentDefinition) {
this.eventListener.componentRegistered(componentDefinition);
}
/**
* Fire an alias-registered event.
*/
public void fireAliasRegistered(String beanName, String alias, @Nullable Object source) {
this.eventListener.aliasRegistered(new AliasDefinition(beanName, alias, source));
}
/**
* Fire an import-processed event.
*/
public void fireImportProcessed(String importedResource, @Nullable Object source) {
this.eventListener.importProcessed(new ImportDefinition(importedResource, source));
}
/**
* Fire an import-processed event.
*/
public void fireImportProcessed(String importedResource, Resource[] actualResources, @Nullable Object source) {
this.eventListener.importProcessed(new ImportDefinition(importedResource, actualResources, source));
}
// Source extraction
/**
* Return the source extractor in use.
*/
public SourceExtractor getSourceExtractor() {
return this.sourceExtractor;
}
/**
* Call the source extractor for the given source object.
*/
@Nullable
public Object extractSource(Object sourceCandidate) {
return this.sourceExtractor.extractSource(sourceCandidate, this.resource);
}
}
主要有几点:错误记录,发布事件和原数据读取,下面也给出了这个ReaderEventListener 接口的源码和spring顶层监听器接口的源码,都比较简单,这里不多解释了
public interface ReaderEventListener extends EventListener {
/**
* Notification that the given defaults has been registered.
*/
void defaultsRegistered(DefaultsDefinition defaultsDefinition);
/**
* Notification that the given component has been registered.
*/
void componentRegistered(ComponentDefinition componentDefinition);
/**
* Notification that the given alias has been registered.
*/
void aliasRegistered(AliasDefinition aliasDefinition);
/**
* Notification that the given import has been processed.
*/
void importProcessed(ImportDefinition importDefinition);
}
public interface EventListener {
}
这里监听器的实现可比其他的源码容易多了,下面给大家稍微演示一下:
public class MyXmlBeanFactory extends DefaultListableBeanFactory {
private XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//原XmlBeanFactory这里的XmlBeanDefinitionReader 是私有的,我这里改了一下
public MyXmlBeanFactory(Resource resource, ReaderEventListener readerEventListener) throws BeansException {
this(resource, null,readerEventListener);
}
public MyXmlBeanFactory(Resource resource, BeanFactory parentBeanFactory,ReaderEventListener readerEventListener) throws BeansException {
super(parentBeanFactory);
this.reader.setEventListener(readerEventListener);
this.reader.loadBeanDefinitions(resource);
}
}
MyReaderEventListener 这里我就对BeanDefiniton创建完毕的事件进行处理
public class MyReaderEventListener implements ReaderEventListener {
@Override
public void defaultsRegistered(DefaultsDefinition defaultsDefinition) {
}
@Override
public void componentRegistered(ComponentDefinition componentDefinition) {
System.out.println("processBeanDefinition-->getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))");
System.out.println("Bean的全类型如下: ");
String beanClassName = componentDefinition.getBeanDefinitions()[0].getBeanClassName();
System.out.println(beanClassName);
System.out.println("调用Peo的show方法: ");
try {
Class<?> aClass = Class.forName(beanClassName);
if(aClass.equals(Peo.class))
{
Peo peo = (Peo) aClass.newInstance();
peo.show();
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
public void aliasRegistered(AliasDefinition aliasDefinition) {
}
@Override
public void importProcessed(ImportDefinition importDefinition) {
}
}
测试:
懂了吗?
我想各位可能都忘记了alias标签被解析的代码是在哪里被调用的了,现在我帮大家回忆一下:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//解析默认标签
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
//解析alias标签
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
protected void processAliasRegistration(Element ele) {
//获取beanName
String name = ele.getAttribute(NAME_ATTRIBUTE);
//获取alias
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
boolean valid = true;
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
//注册别名---上面讲过了
//getReaderContext在这里也被用到了
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));
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
//解析import标签
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
protected void importBeanDefinitionResource(Element ele) {
//获取resource属性指定的资源路径
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// Resolve system properties: e.g. "${user.dir}"
//解析系统属性,例如"${user.dir}"
//这里也用到了getReaderContext
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<>(4);
// Discover whether the location is an absolute or relative URI---判断资源路径是绝对路径还是相对路径
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {
// cannot convert to an URI, considering the location relative
// unless it is the well-known Spring prefix "classpath*:"
}
// Absolute or relative?
//如果是绝对路径就直接加载配置文件
if (absoluteLocation) {
try {
//getReaderContext().getReader()---->xmlBeanDefinition--->loadBeanDefinitions是不是又回到起点了
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isTraceEnabled()) {
logger.trace("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
else {
//如果是相对路径
// No URL -> considering resource location as relative to the current file.
try {
int importCount;
//根据相对路径来定位资源
Resource relativeResource = getReaderContext().getResource().createRelative(location);
//如果资源存在就加载指定的配置文件
if (relativeResource.exists()) {
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
else {
//否则尝试使用传入的resource的url作为基础路径进行查找
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isTraceEnabled()) {
logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
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);
}
}
//进行监听器激活处理
Resource[] actResArray = actualResources.toArray(new Resource[0]);
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse---把当前beans标签作为根节点从头循环一遍,个人认为这里还蛮有意思的
doRegisterBeanDefinitions(ele);
}
}