溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring實(shí)現(xiàn)解析默認(rèn)標(biāo)簽的方法

發(fā)布時(shí)間:2021-06-26 09:41:42 來(lái)源:億速云 閱讀:168 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要講解了“Spring實(shí)現(xiàn)解析默認(rèn)標(biāo)簽的方法”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Spring實(shí)現(xiàn)解析默認(rèn)標(biāo)簽的方法”吧!

1、解析默認(rèn)標(biāo)簽

parseDefaultElement(ele, delegate);

void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   //解析import標(biāo)簽
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
   }
   //解析alias標(biāo)簽
   else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      processAliasRegistration(ele);
   }
    //解析bean標(biāo)簽
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      processBeanDefinition(ele, delegate);
   }
   //解析beans標(biāo)簽,遞歸處理
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      doRegisterBeanDefinitions(ele);
   }
}

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   //1.委托BeanDefinitionPaserDelegate類進(jìn)行元素解析,將BeanDefinition封裝進(jìn)BeanDefinitionHolder里面
   //包含class、name、id屬性
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

   if (bdHolder != null) {
      //2.若默認(rèn)標(biāo)簽的子節(jié)點(diǎn)下有自定義屬性,還需要再對(duì)自定義標(biāo)簽解析
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         //3.委托BeanDefinitionReaderUtils注冊(cè)
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,  getReaderContext().getRegistry());
      }
      //4.發(fā)出響應(yīng)事件,通知想關(guān)心的監(jiān)聽(tīng)事件
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}

2、解析BeanDefinition

BeanDefinition是一個(gè)接口,其抽象實(shí)現(xiàn)類為AbstractBeanDefinition,有三個(gè)子類,分別為RootBeanDefinition、ChildBeanDefinition
和GenericBeanDefinition. BeanDefinition是配置文件bean元素在容器中的內(nèi)部表現(xiàn)形式,和bean中屬性一一對(duì)應(yīng).Spring通過(guò)
BeanDefinition將配置文件中的bean配置信息轉(zhuǎn)換為容器的內(nèi)部表示,并將這些信息注冊(cè)到BeanDefinitionRegistry中,它就是Spring
配置信息的內(nèi)存數(shù)據(jù)庫(kù),是一個(gè)Map,后續(xù)操作直接從該BeanDefinitionRegistry中讀取配置信息.

Spring實(shí)現(xiàn)解析默認(rèn)標(biāo)簽的方法

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
   return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
   //解析id屬性
   String id = ele.getAttribute(ID_ATTRIBUTE);
   //解析name屬性
   String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
   
   //若nameAttr不為空,解析別名屬性
   List<String> aliases = new ArrayList<String>();
   if (StringUtils.hasLength(nameAttr)) {
      String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
      aliases.addAll(Arrays.asList(nameArr));
   }

   String beanName = id;
   //若沒(méi)有指定id屬性,使用別名的第一個(gè)代替
   if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
      beanName = aliases.remove(0);
   }

   if (containingBean == null) {
      checkNameUniqueness(beanName, aliases, ele);
   }
   
   //進(jìn)一步解析其他所有屬性并封裝到beanDefinition中
   AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
   
   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);
               }
            }
         }
      }
      String[] aliasesArray = StringUtils.toStringArray(aliases);
      return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
   }

   return null;
}
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {

   String className = null;
   //解析className屬性
   if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
      className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
   }
   try {
      String parent = null;
      //解析parent屬性
      if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
         parent = ele.getAttribute(PARENT_ATTRIBUTE);
      }

      //創(chuàng)建用于承載屬性的GenericBeanDefinition,直接new的,并set傳進(jìn)去的參數(shù)
      AbstractBeanDefinition bd = createBeanDefinition(className, parent);

      //1.硬編碼解析bean的各種屬性
      parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

      //2.解析description
      bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

      //3.解析元數(shù)據(jù)
      parseMetaElements(ele, bd);

      //4.解析lookup-method屬性,見(jiàn)附錄1,實(shí)際要返回的bean是在配置文件里面配置的
      parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

      //5.解析replace-method屬性,不但可以動(dòng)態(tài)地替換返回實(shí)體的bean,而且還能動(dòng)態(tài)地更改原有方法的邏輯
      parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

      //6.解析構(gòu)造函數(shù)參數(shù),property元素和qualifier元素
      parseConstructorArgElements(ele, bd);
      parsePropertyElements(ele, bd);
      parseQualifierElements(ele, bd);

      bd.setResource(this.readerContext.getResource());
      bd.setSource(extractSource(ele));

      return bd;
   }
}
步驟1:硬編碼解析bean的各種屬性
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String 
                                                    beanName,BeanDefinition containingBean, AbstractBeanDefinition bd) {
   //解析scope屬性
   if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
      bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
      if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
         error("Specify either 'scope' or 'singleton', not both", ele);
      }
   }
   //解析singleton屬性
   else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
      bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ?
                                                       BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
   }
   else if (containingBean != null) {
      bd.setScope(containingBean.getScope());
   }

   if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
      bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
   }
   
   //解析lazy-init屬性,若不設(shè)置或者設(shè)置成其他字符都會(huì)設(shè)置為false
   String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
   if (DEFAULT_VALUE.equals(lazyInit)) {
      lazyInit = this.defaults.getLazyInit();
   }
   bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

   //解析autowire屬性
   String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
   bd.setAutowireMode(getAutowireMode(autowire));

   String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
   bd.setDependencyCheck(getDependencyCheck(dependencyCheck));

   if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
      String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
      bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
   }

   String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
   if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
      String candidatePattern = this.defaults.getAutowireCandidates();
      if (candidatePattern != null) {
         String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
         bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
      }
   }
   else {
      bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
   }

   if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
      bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
   }
   
   //解析init-method屬性
   if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
      String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
      if (!"".equals(initMethodName)) {
         bd.setInitMethodName(initMethodName);
      }
   }
   else {
      if (this.defaults.getInitMethod() != null) {
         bd.setInitMethodName(this.defaults.getInitMethod());
         bd.setEnforceInitMethod(false);
      }
   }
   
   //解析destroy-method屬性
   if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
      String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
      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_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;
}
步驟4、5:見(jiàn)附錄1、2

步驟6:解析構(gòu)造函數(shù)參數(shù)

3、AbstractBeanDefinition

上述解析后的數(shù)據(jù)都放在AbstractBeanDefinition中.
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {

   private volatile Object beanClass;

   private String scope = SCOPE_DEFAULT;

   private boolean singleton = true;

   private boolean prototype = false;

   private boolean abstractFlag = false;

   private boolean lazyInit = false;

   private int autowireMode = AUTOWIRE_NO;

   private int dependencyCheck = DEPENDENCY_CHECK_NONE;

   private String[] dependsOn;
   //構(gòu)造函數(shù)屬性
   private ConstructorArgumentValues constructorArgumentValues;
   //普通屬性集合
   private MutablePropertyValues propertyValues;
   //方法重寫的持有者,記錄lookup-method、replace-method元素
   private MethodOverrides methodOverrides = new MethodOverrides();

   private String factoryBeanName;

   private String factoryMethodName;

   private String initMethodName;

   private String destroyMethodName;
   //是否執(zhí)行init-method和destroy-method
   private boolean enforceInitMethod = true;

   private boolean enforceDestroyMethod = true;
}

4、注冊(cè)BeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   //解析BeanDefinition
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

   if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         //注冊(cè)BeanDefinition到registry
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      //通知監(jiān)聽(tīng)器解析及完成注冊(cè),當(dāng)程序開(kāi)發(fā)人員需要對(duì)注冊(cè)BeanDefinition事件進(jìn)行監(jiān)聽(tīng)時(shí)可以通過(guò)注冊(cè)監(jiān)聽(tīng)器的方
      //式并將處理邏輯寫入監(jiān)聽(tīng)器中,目前Spring中沒(méi)有對(duì)此事件做任何邏輯處理
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry){
   
String beanName = definitionHolder.getBeanName();
   //使用beanName做唯一標(biāo)識(shí)注冊(cè)
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String aliase : aliases) {
         //使用別名做注冊(cè)
         registry.registerAlias(beanName, aliase);
      }
   }
}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {

   if (beanDefinition instanceof AbstractBeanDefinition) {
      try {
         //做校驗(yàn),拋異常部分已刪除
         ((AbstractBeanDefinition) beanDefinition).validate();
      }
   }

   //beanDefinitionMap就是存放注冊(cè)信息的全局變量,會(huì)存在并發(fā)訪問(wèn)的情況,加鎖,它是ConcurrentHashMap
   //Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);
   synchronized (this.beanDefinitionMap) {
      Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
      //處理已經(jīng)注冊(cè)beanName的情況
      if (oldBeanDefinition != null) {
         if (!this.allowBeanDefinitionOverriding) {
             //此處代碼簡(jiǎn)略了,不允許覆蓋則拋異常,允許覆蓋則記錄下日志
         }
      }
      else {
         this.beanDefinitionNames.add(beanName);
         this.frozenBeanDefinitionNames = null;
      }
      //真正進(jìn)行注冊(cè)
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   //清除緩存
   resetBeanDefinition(beanName);
}

5、解析alias標(biāo)簽

protected void processAliasRegistration(Element ele) {
   //獲取beanName
   String name = ele.getAttribute(NAME_ATTRIBUTE);
   //獲取別名alias
   String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
   boolean valid = true;
   //之前有一些校驗(yàn),刪掉了
   if (valid) {
      try {
         //注冊(cè)
         getReaderContext().getRegistry().registerAlias(name, alias);
      }
      getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
   }
}

6、解析import標(biāo)簽

protected void importBeanDefinitionResource(Element ele) {
   //解析resource屬性,形如<import resource=”***.xml”/>
   String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
   //不存在直接返回
   if (!StringUtils.hasText(location)) {
      getReaderContext().error("Resource location must not be empty", ele);
      return;
   }

   location = environment.resolveRequiredPlaceholders(location);
   Set<Resource> actualResources = new LinkedHashSet<Resource>(4);
   //判斷是相對(duì)路徑還是絕對(duì)路徑
   boolean absoluteLocation = false;
   try {
      absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
   }
 
   if (absoluteLocation) {
      try {
         //是絕對(duì)路徑,直接調(diào)用loadBeanDefinitions加載BeanDefinition,遞歸操作
         int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
      }
   }else {
      try {
         int importCount;
         //計(jì)算出絕對(duì)路徑,進(jìn)行l(wèi)oadBeanDefinitons
         Resource relativeResource = getReaderContext().getResource().createRelative(location);
         if (relativeResource.exists()) {
            importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
            actualResources.add(relativeResource);
         }
         else {
            String baseLocation = getReaderContext().getResource().getURL().toString();
            importCount = getReaderContext().getReader().loadBeanDefinitions(
                  StringUtils.applyRelativePath(baseLocation, location), actualResources);
         }
      }
 }
   Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
   getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
附錄1:解析lookup-method
public class User {
    public void showMe(){
        System.out.println("I am a User");
    }
}

public class Teacher extends User{
    @Override
    public void showMe() {
        System.out.println("I am a teacher");
    }
}

public abstract class GetBeanTest {

    public void showMe(){
        this.getBean().showMe();
    }

    public abstract User getBean();
}
<bean id="getBeanTest" class="com.lwh.spring.look.GetBeanTest">
    <lookup-method name="getBean" bean="teacher"/>
</bean>

<bean id="teacher" class="com.lwh.spring.look.Teacher"/>
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)){
         Element ele = (Element) node;
         //獲取要修飾的方法
         String methodName = ele.getAttribute(NAME_ATTRIBUTE);
         //獲取配置返回的bean
         String beanRef = ele.getAttribute(BEAN_ELEMENT);
         LookupOverride override = new LookupOverride(methodName, beanRef);
         override.setSource(extractSource(ele));
         overrides.addOverride(override);
      }
   }
}

Spring實(shí)現(xiàn)解析默認(rèn)標(biāo)簽的方法

附錄2:解析replace-method
public class TestChangeMethod {
    public void changeMe(){
        System.out.println("changeMe");
    }
}

public class TestMethodReplacer implements MethodReplacer{

    public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
        System.out.println("我替換了原有的方法");
        return null;
    }
}
<bean id="testChangeMethod" class="com.lwh.spring.replace.TestChangeMethod">
    <replaced-method name="changeMe" replacer="replacer"/>
</bean>

<bean id="replacer" class="com.lwh.spring.replace.TestMethodReplacer"/>
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)在Spring默認(rèn)bean的子元素下且為replace-method時(shí)才有效
      if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
         Element replacedMethodEle = (Element) node;
         //提取要替換的舊的方法,changeMe
         String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
         //提取對(duì)應(yīng)的新的替換方法,replacer
         String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
         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) {
            //記錄參數(shù)
            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.addOverride(replaceOverride);
      }
   }
}

感謝各位的閱讀,以上就是“Spring實(shí)現(xiàn)解析默認(rèn)標(biāo)簽的方法”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Spring實(shí)現(xiàn)解析默認(rèn)標(biāo)簽的方法這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI