上一節(jié) 我們說到 IOC容器的基本實(shí)現(xiàn),分析到解析標(biāo)簽 :如以下代碼
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) { //判斷是否使用了默認(rèn)的命名空間 如果是則,執(zhí)行一下代碼 如果不是 執(zhí)行自定義標(biāo)簽的解析
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);//執(zhí)行默認(rèn)標(biāo)簽的解析
} else {
delegate.parseCustomElement(ele);//執(zhí)行自定義標(biāo)簽的解析
}
}
}
} else {
delegate.parseCustomElement(root);//執(zhí)行自定義標(biāo)簽的解析
}
}
現(xiàn)在我們就先分析下 執(zhí)行默認(rèn)標(biāo)簽的解析:點(diǎn)入parseDefaultElement(ele, delegate)方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);//解析import 標(biāo)簽
} else if (delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);//解析alias 標(biāo)簽
} else if (delegate.nodeNameEquals(ele, "bean")) {
this.processBeanDefinition(ele, delegate);//解析bean標(biāo)簽
} else if (delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);//解析beans標(biāo)簽
}
}
如以上我們分析了 Spring解析4種標(biāo)簽:import標(biāo)簽, alias標(biāo)簽狱窘, bean標(biāo)簽和beans標(biāo)簽摔吏,這里我們重點(diǎn)分析一下 如何解析bean標(biāo)簽
解析bean標(biāo)簽
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);//委托delegate解析
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//如果beanHolder 不為空 ,則進(jìn)行裝配
try {
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());//開始注冊bean
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));//通知監(jiān)聽器以及边酒,這個(gè)bean已經(jīng)加載完成
}
}
1.委托delegate.parseBeanDefinitionElement()方法進(jìn)行解析赂摆,將解析后的值封裝到BeanDefinitionHolder 的實(shí)例bdHolder中挟憔,此時(shí)我們的BeanDefintionHolder以及有配置文件中的各個(gè)屬性了钟些,如Class name id之類的屬性
2.如果bean不為空的情況下,若存在bean標(biāo)簽的子節(jié)點(diǎn)再有在定義屬性绊谭,還需要對bean標(biāo)簽再次進(jìn)行解析
3.解析完成 之后的注冊交給了registerBeanDefinition()方法
提取bean信息
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute("id");//提取id
String nameAttr = ele.getAttribute("name");//提取name
List<String> aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if (this.logger.isDebugEnabled()) {
this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
this.checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);//提取bean標(biāo)簽的其他屬性 進(jìn)一步封裝到GenericbeanDefaintion中
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
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);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
1.提取id和name的屬性
2.進(jìn)一步解析其他屬性 封裝到GenericBeanDefinition類型的實(shí)例中
3.檢測beanName,如果沒有beanName,則默認(rèn)使用Bean為他生成BeanName
4.將解析出來的信息封裝到BeanDefinitionHolder的實(shí)例中
解析其他標(biāo)簽的屬性
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute("class")) { //解析Class屬性
className = ele.getAttribute("class").trim();
}
try {
String parent = null;
if (ele.hasAttribute("parent")) {//解析parent屬性
parent = ele.getAttribute("parent");
}
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);//創(chuàng)建用與承載屬性 AbstractBeanDefintion 類型的GenericBeanDefinition實(shí)例
//硬編碼解析默認(rèn)bean的各個(gè)屬性
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//解析Description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//解析meta
this.parseMetaElements(ele, bd);
//解析LookUp-method
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析Replaced-method
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析構(gòu)造函數(shù)參數(shù)
this.parseConstructorArgElements(ele, bd);
//解析Property元素
this.parsePropertyElements(ele, bd);
//解析Qualifier子元素
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
} catch (ClassNotFoundException var13) {
this.error("Bean class [" + className + "] not found", ele, var13);
} catch (NoClassDefFoundError var14) {
this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
} catch (Throwable var15) {
this.error("Unexpected failure during bean definition parsing", ele, var15);
} finally {
this.parseState.pop();
}
return null;
}
創(chuàng)建用于屬性承載的BeanDefinition
beanDefinition 是一個(gè)接口 用三種實(shí)現(xiàn) RootBeanDefinition,ChildBeanDefinition以及GenericBeanDefinition 這三種均實(shí)現(xiàn)了AbstractBeanDefinitionBean 它們之間的關(guān)系如下圖:
由此可見 首先就是要?jiǎng)?chuàng)建 承載屬性的實(shí)例政恍,也就是創(chuàng)建GenericBeanDefintion 類型的實(shí)例
public static AbstractBeanDefinition createBeanDefinition(String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
} else {
bd.setBeanClassName(className); //記錄ClassName
}
}
return bd;
}
創(chuàng)建完用于屬性承載的BeanDefinition 接下來就是 解析各種屬性了
解析各種屬性
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
是對Element所有元素進(jìn)行解析
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) {
if (ele.hasAttribute("scope")) { //解析Scope屬性
bd.setScope(ele.getAttribute("scope"));
} else if (containingBean != null) {
bd.setScope(containingBean.getScope());
}
if (ele.hasAttribute("abstract")) {//解析abstract屬性
bd.setAbstract("true".equals(ele.getAttribute("abstract")));
}
String lazyInit = ele.getAttribute("lazy-init");
if ("default".equals(lazyInit)) { //解析lazy-init 屬性
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit("true".equals(lazyInit));
String autowire = ele.getAttribute("autowire");//解析autowire屬性
bd.setAutowireMode(this.getAutowireMode(autowire));
String dependencyCheck = ele.getAttribute("dependency-check")//解析dependency-check屬性;
bd.setDependencyCheck(this.getDependencyCheck(dependencyCheck));
String autowireCandidate;
if (ele.hasAttribute("depends-on")) {//解析denpends-on屬性
autowireCandidate = ele.getAttribute("depends-on");
bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; "));
}
//解析autowire-candidate 屬性
autowireCandidate = ele.getAttribute("autowire-candidate");
String destroyMethodName;
if (!"".equals(autowireCandidate) && !"default".equals(autowireCandidate)) {
bd.setAutowireCandidate("true".equals(autowireCandidate));
} else {
destroyMethodName = this.defaults.getAutowireCandidates();
if (destroyMethodName != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
}
//解析primary 屬性
if (ele.hasAttribute("primary")) {
bd.setPrimary("true".equals(ele.getAttribute("primary")));
}
//解析init-method 屬性
if (ele.hasAttribute("init-method")) {
destroyMethodName = ele.getAttribute("init-method");
if (!"".equals(destroyMethodName)) {
bd.setInitMethodName(destroyMethodName);
}
} else if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
//解析destroy-method 屬性
if (ele.hasAttribute("destroy-method")) {
destroyMethodName = ele.getAttribute("destroy-method");
if (!"".equals(destroyMethodName)) {
bd.setDestroyMethodName(destroyMethodName);
}
} else if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
//解析factory-method屬性
if (ele.hasAttribute("factory-method")) {
bd.setFactoryMethodName(ele.getAttribute("factory-method"));
}
//解析factory-bean屬性
if (ele.hasAttribute("factory-bean")) {
bd.setFactoryBeanName(ele.getAttribute("factory-bean"));
}
return bd;
}
我們清楚的看見了 Spring對各個(gè)標(biāo)簽的解析 包括 我們經(jīng)常用到的,不經(jīng)常用的都進(jìn)行了解析达传,解析來就讓我們分析Spring 是如何 解析各個(gè)元素的篙耗。
解析Meta子標(biāo)簽
<bean id ="myTestMeta" class="com.zhh.MyTestMeta">
<meta key="testStr" value="testValue"/>
</bean>
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
NodeList nl = ele.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//判斷當(dāng)前節(jié)點(diǎn)是否是Meta
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "meta")) {
Element metaElement = (Element)node;
String key = metaElement.getAttribute("key");
String value = metaElement.getAttribute("value");
//使用BeanMetadataAttribute 封裝Meta 的Key和Value
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(this.extractSource(metaElement));
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
解析子標(biāo)簽LookUp-method
或許LookUp-method 子標(biāo)簽并不常用 我們通過一個(gè)列子來說明
public Class User{
public void showme(){
System.out.println("I am User");
}
}
public Class Teacher Extends User{
public void showme(){
System.out.println("i am teaacher");
}
}
//創(chuàng)建調(diào)用方法
public abstract class GetBeanTest{
public void showme(){
this.getBean.showme();
}
public abstract User getBean();
}
//xml配置
<bean id="getBeanTest" class="com.zhh.GetBeanTest">
<lookup-method name="getBean" bean="teacher"/>
</bean>
<bean id="teacher" class="com.zhh.Teacher"/>
//運(yùn)行結(jié)果
i an Teacher
抽象方法沒有被實(shí)現(xiàn) 怎么會被調(diào)用呢 我們看配置 完成的功能是,動(dòng)態(tài)的將teacher所代表的的bean 作為getBean的返回值 宪赶。我們看是如何解析的
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//當(dāng)且僅當(dāng) 當(dāng)前子標(biāo)簽lookup-method 是在進(jìn)行解析
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "lookup-method")) {
Element ele = (Element)node;
String methodName = ele.getAttribute("name");
String beanRef = ele.getAttribute("bean");
//使用lookupOverride 封裝name和bean元素
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(this.extractSource(ele));
overrides.addOverride(override);
}
}
}
解析replaced-method 子標(biāo)簽
如果說 lookup-method 中的屬性bean 所代表的的bean 作為屬性name 的返回值宗弯。那么replaced-method 可以動(dòng)態(tài)的改變 原有方法的邏輯
public class TestChangeMethod(){
public void changeMethod(){
Sytem.out.println("change me");
}
}
//如果有一天 在上線后 要改變原有的邏輯怎么辦?
pulic class TestMethodReplacer implements org.springframework.beans.factory.support.MethodReplacer{
public Object reimplement(Object obj,Method method,Object []){
System.out.println("我替換了原來的方法.....");
return null搂妻;
}
}
//xml 這樣配置
<bean id="testChangeMethod" class="test.replacemethod.TestChangeMethod">
<replaced-method name="changeMe" replace="replace">
</bean>
<bean id ="replace" class="com.zhh.TestMethodReplacer"/>
解析來我們看是如何解析的 replace-method標(biāo)簽的
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//判斷當(dāng)前標(biāo)簽是否是replaced-method 字標(biāo)簽
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "replaced-method")) {
Element replacedMethodEle = (Element)node;
//提取要替換舊的方法的名稱
String name = replacedMethodEle.getAttribute("name");
//提取對應(yīng)的新的替換方法
String callback = replacedMethodEle.getAttribute("replacer");
//創(chuàng)建用于封裝name和replace 的實(shí)例bean ReplaceOverride
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, "arg-type");
Iterator var11 = argTypeEles.iterator();
while(var11.hasNext()) {
Element argTypeEle = (Element)var11.next();
String match = argTypeEle.getAttribute("match");
match = StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle);
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(this.extractSource(replacedMethodEle));
overrides.addOverride(replaceOverride);
}
}
}
解析子元素Conctructor-arg
Conctructor-age 字標(biāo)簽是非常常用的
<bean id ="helloBean" class="com.zhh.hellobean">
<conctructor-arg index="0">
<value>aaaa</value>
</conctructor-arg>
</bean>
以上是conctructor-arg最基本的用法 那么我們看是如何解析的蒙保?
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
String indexAttr = ele.getAttribute("index");//獲取index 屬性
String typeAttr = ele.getAttribute("type");//獲取type屬性
String nameAttr = ele.getAttribute("name");//獲取name屬性
if (StringUtils.hasLength(indexAttr)) { //判斷是否有index屬性
try {
int index = Integer.parseInt(indexAttr);
if (index < 0) {
this.error("'index' cannot be lower than 0", ele);
} else {
try {
this.parseState.push(new ConstructorArgumentEntry(index));
Object value = this.parsePropertyValue(ele, bd, (String)null);
ValueHolder valueHolder = new ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(this.extractSource(ele));
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
this.error("Ambiguous constructor-arg entries for index " + index, ele);
} else {
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
}
} finally {
this.parseState.pop();
}
}
} catch (NumberFormatException var19) {
this.error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
} else {
//沒有index屬性自動(dòng)尋找
try {
this.parseState.push(new ConstructorArgumentEntry());
Object value = this.parsePropertyValue(ele, bd, (String)null);
ValueHolder valueHolder = new ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(this.extractSource(ele));
bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
} finally {
this.parseState.pop();
}
}
}
1.判斷是否有index屬性 ,有 則步驟如下
1.1 解析constructor-arg的子元素
1.2 使用ConstructorArgmentValues.ValueHolder封裝 解析出來的元素
1.3 將 封裝的元素添加到BeanDefinition中的ContrucotrAgrmentValues的IndexedArgumentValue元素中
2.沒有則步驟如下
1.1 解析constructor-arg的子元素
1.2 使用ConstructorArgmentValues.ValueHolder封裝 解析出來的元素
1.3 將 封裝的元素添加到BeanDefinition中的ContrucotrAgrmentValues的GenericArgumentValue元素中
沒有Index和 有index 關(guān)鍵在于封裝的位置不同 有Index屬性封裝在IndexedArgumentValue 沒有封裝在 GenericArgumentValue中
那么我們分析一下 parsePropertyValue()這個(gè)方法
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = propertyName != null ? "<property> element for property '" + propertyName + "'" : "<constructor-arg> element";
NodeList nl = ele.getChildNodes();
Element subElement = null;
//一個(gè)屬性只能對應(yīng)一種類型
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//對description和meta 不做處理
if (node instanceof Element && !this.nodeNameEquals(node, "description") && !this.nodeNameEquals(node, "meta")) {
if (subElement != null) {
this.error(elementName + " must not contain more than one sub-element", ele);
} else {
subElement = (Element)node;
}
}
}
//提取ref屬性
boolean hasRefAttribute = ele.hasAttribute("ref");
boolean hasValueAttribute = ele.hasAttribute("value");//提取value屬性
if (hasRefAttribute && hasValueAttribute || (hasRefAttribute || hasValueAttribute) && subElement != null) {
//Contructor-age上不存在
//既有ref屬性又有value屬性 存在ref又有子元素或者value屬性又有子元素
this.error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
//對ref的處理 用RuntimeBeanReference 封裝
if (hasRefAttribute) {
String refName = ele.getAttribute("ref");
if (!StringUtils.hasText(refName)) {
this.error(elementName + " contains empty 'ref' attribute", ele);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(this.extractSource(ele));
return ref;
} else if (hasValueAttribute) {//對value屬性的處理 用 TypedStringValue封裝
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute("value"));
valueHolder.setSource(this.extractSource(ele));
return valueHolder;
} else if (subElement != null) {//解析子元素
return this.parsePropertySubElement(subElement, bd);
} else {
this.error(elementName + " must specify a ref or value", ele);
return null;
}
}
上述步驟可以分為:
1.不提取description和meta
2.提取ref和value屬性 同時(shí)判斷不能同時(shí)存在ref屬性和value屬性
3.對ref屬性進(jìn)行提取 用RuntimeBeanReference封裝
4.對value屬性進(jìn)行提取 用 TypedStringValue封裝
5.對子元素進(jìn)行解析
<constructor-arg>
<map>
<entry key="key" value="value"/>
</map>
</constructor-arg>
則對子元素進(jìn)行提取欲主,則解析過程如下
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
if (!this.isDefaultNamespace((Node)ele)) {
return this.parseNestedCustomElement(ele, bd);
} else if (this.nodeNameEquals(ele, "bean")) {
BeanDefinitionHolder nestedBd = this.parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = this.decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
} else if (this.nodeNameEquals(ele, "ref")) {
String refName = ele.getAttribute("bean");
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
refName = ele.getAttribute("local");//解析local
if (!StringUtils.hasLength(refName)) {
refName = ele.getAttribute("parent"); //解析parent
toParent = true;
if (!StringUtils.hasLength(refName)) {
this.error("'bean', 'local' or 'parent' is required for <ref> element", ele);
return null;
}
}
}
if (!StringUtils.hasText(refName)) {
this.error("<ref> element contains empty target attribute", ele);
return null;
} else {
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
ref.setSource(this.extractSource(ele));
return ref;
}
} else if (this.nodeNameEquals(ele, "idref")) {//對idref元素進(jìn)行解析
return this.parseIdRefElement(ele);
} else if (this.nodeNameEquals(ele, "value")) {//對Value進(jìn)行解析
return this.parseValueElement(ele, defaultValueType);
} else if (this.nodeNameEquals(ele, "null")) {//對null 進(jìn)行解析
TypedStringValue nullHolder = new TypedStringValue((String)null);
nullHolder.setSource(this.extractSource(ele));
return nullHolder;
} else if (this.nodeNameEquals(ele, "array")) {//對array進(jìn)行解析
return this.parseArrayElement(ele, bd);
} else if (this.nodeNameEquals(ele, "list")) {//對list進(jìn)行解析
return this.parseListElement(ele, bd);
} else if (this.nodeNameEquals(ele, "set")) {/對set進(jìn)行解析
return this.parseSetElement(ele, bd);
} else if (this.nodeNameEquals(ele, "map")) {//對map進(jìn)行解析
return this.parseMapElement(ele, bd);
} else if (this.nodeNameEquals(ele, "props")) {//對props進(jìn)行解析
return this.parsePropsElement(ele);
} else {
this.error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
解析子標(biāo)簽property
public void parsePropertyElement(Element ele, BeanDefinition bd) {
String propertyName = ele.getAttribute("name");//解析屬性name的值
if (!StringUtils.hasLength(propertyName)) {
this.error("Tag 'property' must have a 'name' attribute", ele);
} else {
this.parseState.push(new PropertyEntry(propertyName));
try {
if (!bd.getPropertyValues().contains(propertyName)) {
Object val = this.parsePropertyValue(ele, bd, propertyName);
PropertyValue pv = new PropertyValue(propertyName, val);//將返回出來的值用PropertyValue 進(jìn)行封裝
this.parseMetaElements(ele, pv);
pv.setSource(this.extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
return;
}
this.error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
} finally {
this.parseState.pop();
}
}
}
解析字標(biāo)簽Qualifier
對Qualifer 的使用如下
<bean id="myTest" class="com.zhh.MyTestBean">
<qualifier type="org.springframeWork.beans.annotaion.Qualifier" value="qf">
</bean>
具體解析如下
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
String typeName = ele.getAttribute("type");//對type進(jìn)行提取
if (!StringUtils.hasLength(typeName)) {
this.error("Tag 'qualifier' must have a 'type' attribute", ele);
} else {
this.parseState.push(new QualifierEntry(typeName));
try {
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);//創(chuàng)建用于封裝type 和 value的AutowireCandidateQualifier
qualifier.setSource(this.extractSource(ele));
String value = ele.getAttribute("value");
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);
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "attribute")) {
Element attributeEle = (Element)node;
String attributeName = attributeEle.getAttribute("key");
String attributeValue = attributeEle.getAttribute("value");
if (!StringUtils.hasLength(attributeName) || !StringUtils.hasLength(attributeValue)) {
this.error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
return;
}
BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
attribute.setSource(this.extractSource(attributeEle));
qualifier.addMetadataAttribute(attribute);
}
}
bd.addQualifier(qualifier);
} finally {
this.parseState.pop();
}
}
}
到這里我們也分析了默認(rèn)標(biāo)簽的解析與提取過程邓厕,當(dāng)前我們分析了
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);這句話
那么我們接著分析 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
其實(shí)程序執(zhí)行到這一步 Spring默認(rèn)的標(biāo)簽以及執(zhí)行完了 而這一步是對自定義標(biāo)簽進(jìn)行解析
注冊解析的BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
//使用beanName作為唯一標(biāo)識
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());//通過BeanName注冊
//獲取所有的別名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String aliase = var4[var6];
registry.registerAlias(beanName, aliase);//通過BeanName注冊別名
}
}
}
從上面我們可以看出,解析的beanDefinition都會注冊到BeanDefinitionRegistry類型的實(shí)例registry中
1.通過BeanName注冊BeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var7) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var7);
}
}
Map var3 = this.beanDefinitionMap;
//因?yàn)閎eanDefinitionMap是全局變量 會存在并發(fā)
synchronized(this.beanDefinitionMap) {
//根據(jù)beanName獲取bean
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) { //如果根據(jù)beanName獲取bean以及存在 并且判斷是否可以覆蓋扁瓢,如果不運(yùn)行覆蓋 則拋出異常
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + " with a framework-generated bean definition ': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else {
this.beanDefinitionNames.add(beanName);//記錄beanName
this.frozenBeanDefinitionNames = null;
}
//注冊BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//重置BeanName對應(yīng)的緩存
this.resetBeanDefinition(beanName);
}
1.根據(jù)beanName獲取BeanDefintion 如果已近注冊的情況下详恼,并且設(shè)置了不允許Bean覆蓋則,需要拋出異常
2.加入map緩存
3.清除之前留下的對應(yīng)的BeanName的緩存
2.通過別名注冊BeanDefinition
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
if (alias.equals(name)) {
this.aliasMap.remove(alias);
} else {
if (!this.allowAliasOverriding()) {//若alias不允許被覆蓋引几,則拋出異常
String registeredName = (String)this.aliasMap.get(alias);
if (registeredName != null && !registeredName.equals(name)) {
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'.");
}
}
this.checkForAliasCircle(name, alias);
this.aliasMap.put(alias, name);
}
}
3.通過監(jiān)聽器解析以及注冊既注冊完成
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));