日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于Xml 的IOC 容器-载入<bean>元素

發布時間:2024/4/13 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Xml 的IOC 容器-载入<bean>元素 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Bean 配置信息中的<import>和<alias>元素解析在DefaultBeanDefinitionDocumentReader 中已經完成,對Bean 配置信息中使用最多的<bean>元素交由BeanDefinitionParserDelegate 來解析,其解析實現的源碼如下:

//解析<Bean>元素的入口 @Nullable public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {return parseBeanDefinitionElement(ele, null); }//解析Bean定義資源文件中的<Bean>元素,這個方法中主要處理<Bean>元素的id,name和別名屬性 @Nullable public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {//獲取<Bean>元素中的id屬性值String id = ele.getAttribute(ID_ATTRIBUTE);//獲取<Bean>元素中的name屬性值String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//獲取<Bean>元素中的alias屬性值List<String> aliases = new ArrayList<>();//將<Bean>元素中的所有name屬性值存放到別名中if (StringUtils.hasLength(nameAttr)) {String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);aliases.addAll(Arrays.asList(nameArr));}String beanName = id;//如果<Bean>元素中沒有配置id屬性時,將別名中的第一個值賦值給beanNameif (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {beanName = aliases.remove(0);if (logger.isDebugEnabled()) {logger.debug("No XML 'id' specified - using '" + beanName +"' as bean name and " + aliases + " as aliases");}}//檢查<Bean>元素所配置的id或者name的唯一性,containingBean標識<Bean>//元素中是否包含子<Bean>元素if (containingBean == null) {//檢查<Bean>元素所配置的id、name或者別名是否重復checkNameUniqueness(beanName, aliases, ele);}//詳細對<Bean>元素中配置的Bean定義進行解析的地方AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);if (beanDefinition != null) {if (!StringUtils.hasText(beanName)) {try {if (containingBean != null) {//如果<Bean>元素中沒有配置id、別名或者name,且沒有包含子元素//<Bean>元素,為解析的Bean生成一個唯一beanName并注冊beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);}else {//如果<Bean>元素中沒有配置id、別名或者name,且包含了子元素//<Bean>元素,為解析的Bean使用別名向IOC容器注冊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.//為解析的Bean使用別名注冊時,為了向后兼容//Spring1.2/2.0,給別名添加類名后綴String beanClassName = beanDefinition.getBeanClassName();if (beanClassName != null &&beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {aliases.add(beanClassName);}}if (logger.isDebugEnabled()) {logger.debug("Neither XML 'id' nor 'name' specified - " +"using generated bean name [" + beanName + "]");}}catch (Exception ex) {error(ex.getMessage(), ele);return null;}}String[] aliasesArray = StringUtils.toStringArray(aliases);return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);}//當解析出錯時,返回nullreturn null; }protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {String foundName = null;if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {foundName = beanName;}if (foundName == null) {foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases);}if (foundName != null) {error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);}this.usedNames.add(beanName);this.usedNames.addAll(aliases); }//詳細對<Bean>元素中配置的Bean定義其他屬性進行解析 //由于上面的方法中已經對Bean的id、name和別名等屬性進行了處理 //該方法中主要處理除這三個以外的其他屬性數據 @Nullable public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {//記錄解析的<Bean>this.parseState.push(new BeanEntry(beanName));//這里只讀取<Bean>元素中配置的class名字,然后載入到BeanDefinition中去//只是記錄配置的class名字,不做實例化,對象的實例化在依賴注入時完成String className = null;//如果<Bean>元素中配置了parent屬性,則獲取parent屬性的值if (ele.hasAttribute(CLASS_ATTRIBUTE)) {className = ele.getAttribute(CLASS_ATTRIBUTE).trim();}String parent = null;if (ele.hasAttribute(PARENT_ATTRIBUTE)) {parent = ele.getAttribute(PARENT_ATTRIBUTE);}try {//根據<Bean>元素配置的class名稱和parent屬性值創建BeanDefinition//為載入Bean定義信息做準備AbstractBeanDefinition bd = createBeanDefinition(className, parent);//對當前的<Bean>元素中配置的一些屬性進行解析和設置,如配置的單態(singleton)屬性等parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);//為<Bean>元素解析的Bean設置description信息bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));//對<Bean>元素的meta(元信息)屬性解析parseMetaElements(ele, bd);//對<Bean>元素的lookup-method屬性解析parseLookupOverrideSubElements(ele, bd.getMethodOverrides());//對<Bean>元素的replaced-method屬性解析parseReplacedMethodSubElements(ele, bd.getMethodOverrides());//解析<Bean>元素的構造方法設置parseConstructorArgElements(ele, bd);//解析<Bean>元素的<property>設置parsePropertyElements(ele, bd);//解析<Bean>元素的qualifier屬性parseQualifierElements(ele, bd);//為當前解析的Bean設置所需的資源和依賴對象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();}//解析<Bean>元素出錯時,返回nullreturn null; }

只要使用過Spring,對Spring 配置文件比較熟悉的人,通過對上述源碼的分析,就會明白我們在Spring配置文件中<Bean>元素的中配置的屬性就是通過該方法解析和設置到Bean 中去的。

注意:在解析<Bean>元素過程中沒有創建和實例化Bean 對象,只是創建了Bean 對象的定義類BeanDefinition,將<Bean>元素中的配置信息設置到BeanDefinition 中作為記錄,當依賴注入時才使用這些記錄信息創建和實例化具體的Bean 對象。

上面方法中一些對一些配置如元信息(meta)、qualifier 等的解析,我們在Spring 中配置時使用的也不多,我們在使用Spring 的<Bean>元素時,配置最多的是<property>屬性,因此我們下面繼續分析源碼,了解Bean 的屬性在解析時是如何設置的。

?

總結

以上是生活随笔為你收集整理的基于Xml 的IOC 容器-载入<bean>元素的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。