最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring通過(guò)<import>標(biāo)簽導(dǎo)入外部配置文件

 更新時(shí)間:2021年06月22日 14:41:54   作者:沉迷Spring  
之前文章里我們講到Spring加載Xml配置文件的細(xì)節(jié),那么加載完了我們肯定要解析這個(gè)配置文件中定義的元素。這篇我們首先來(lái)分析下Spring是如何通過(guò)標(biāo)簽導(dǎo)入外部配置文件的。

示例

我們先來(lái)看下配置文件是怎么導(dǎo)入外部配置文件的?先定義一個(gè)spring-import配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
   <import resource="spring-config.xml"/>
   <bean id="innerPerson" class="com.john.aop.Person">
   </bean>
</beans>

我們看到里面定義了一個(gè)標(biāo)簽并用屬性resource聲明了導(dǎo)入的資源文件為spring-config.xml。我們?cè)賮?lái)看下spring-config.xml配置文件是怎樣的:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="outerPerson" class="com.john.aop.Person">
          <property name="firstName" value="john"/>
            <property name="lastName" value="wonder"/>
   </bean>
   <bean id="ChineseFemaleSinger" class="com.john.beanFactory.Singer" abstract="true" >
      <property name="country" value="中國(guó)"/>
      <property name="gender" value="女"/>
   </bean>
</beans>

然后我們可以實(shí)例化一個(gè)BeanFactory來(lái)加載spring-import這個(gè)配置文件了。

public static void main(String[] args) {
   ApplicationContext context=new ClassPathXmlApplicationContext("spring-import.xml");
   Person outerPerson=(Person)context.getBean("outerPerson");
   System.out.println(outerPerson);
}

如果沒(méi)問(wèn)題的話,我們可以獲取到outerPerson這個(gè)bean并打印了。

Person [0, john wonder]

原理

我們來(lái)通過(guò)源碼分析下Spring是如何解析import標(biāo)簽并加載這個(gè)導(dǎo)入的配置文件的。首先我們到DefaultBeanDefinitionDocumentReader類中看下:

DefaultBeanDefinitionDocumentReader

我們可以看到類里面定義了一個(gè)public static final 的IMPORT_ELEMENT變量:

public static final String IMPORT_ELEMENT = "import";

然后我們可以搜索下哪邊用到了這個(gè)變量,并且定位到parseDefaultElement函數(shù):

parseDefaultElement

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   //todo  對(duì) import 標(biāo)簽的解析 2020-11-17
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
   }
}

這里就是我們要找的導(dǎo)入外部配置文件加載Bean定義的源代碼,我們?cè)僦攸c(diǎn)看下importBeanDefinitionResource函數(shù):

importBeanDefinitionResource

/**
 * Parse an "import" element and load the bean definitions
 * from the given resource into the bean factory.
 */
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}"
   // // 解析系統(tǒng)屬性,格式如 :"${user.dir}"
   location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
   Set<Resource> actualResources = new LinkedHashSet<>(4);
   // Discover whether the location is an absolute or relative URI
   //// 判斷 location 是相對(duì)路徑還是絕對(duì)路徑
   boolean absoluteLocation = false;
   try {
      //以 classpath*: 或者 classpath: 開(kāi)頭為絕對(duì)路徑
      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?
   //絕對(duì)路徑 也會(huì)調(diào)用loadBeanDefinitions
   if (absoluteLocation) {
      try {
         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 {
      //如果是相對(duì)路徑,則先計(jì)算出絕對(duì)路徑得到 Resource,然后進(jìn)行解析
      // No URL -> considering resource location as relative to the current file.
      try {
         int importCount;
         Resource relativeResource = getReaderContext().getResource().createRelative(location);

         //如果相對(duì)路徑 這個(gè)資源存在 那么就加載這個(gè)bean 定義
         if (relativeResource.exists()) {
            importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
            actualResources.add(relativeResource);
         }
         else {
            String baseLocation = getReaderContext().getResource().getURL().toString();
            //todo import節(jié)點(diǎn) 內(nèi)部會(huì)調(diào)用loadBeanDefinitions 操作 2020-10-17
            importCount = getReaderContext().getReader().loadBeanDefinitions(
                  StringUtils.applyRelativePath(baseLocation, location), actualResources);
         }
         if (logger.isTraceEnabled()) {
            logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]");
         }
      }
   }
}

我們來(lái)解析下這段代碼是怎么一個(gè)流程:

1.首先通過(guò)resource標(biāo)簽解析到它的屬性值,并且判讀字符串值是否為空。

2.接下來(lái)它還會(huì)通過(guò)當(dāng)前上下文環(huán)境去解析字符串路徑里面的占位符,這點(diǎn)我們?cè)谥拔恼轮蟹治鲞^(guò)。

2.接下來(lái)判斷是否是絕對(duì)路徑,通過(guò)調(diào)用ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();來(lái)判斷,劃重點(diǎn):以 classpath*: 或者 classpath: 開(kāi)頭為絕對(duì)路徑,或者可以生成一個(gè)URI實(shí)例就是當(dāng)作絕對(duì)路徑,或者也可以URI的isAbsolute來(lái)判斷

3.如果是絕對(duì)路徑那么我們通過(guò)getReaderContext().getReader()獲取到XmlBeanDefinitionReader然后調(diào)用它的loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources)函數(shù)

4.如果不是絕對(duì)路徑那么我們嘗試生成相對(duì)當(dāng)前資源的路徑(這點(diǎn)很重要),再通過(guò)loadBeanDefinitions方法來(lái)加載這個(gè)配置文件中的BeanDefinitions。這里有個(gè)細(xì)節(jié)需要我們注意,就是它為什么要嘗試去判斷資源是否存在?就是如果存在的話那么直接調(diào)用loadBeanDefinitions(Resource resource)方法,也就是說(shuō)這里肯定是加載單個(gè)資源文件,如方法注釋所說(shuō):

/**
 * Load bean definitions from the specified XML file.
 * @param resource the resource descriptor for the XML file
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 */
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
   //load中去注冊(cè)BeanDefinition
   return loadBeanDefinitions(new EncodedResource(resource));
}

從指定的xml文件加載Bean定義。如果不存在,那么就跟絕對(duì)路徑一樣會(huì)調(diào)用loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources)函數(shù),我們來(lái)看看這個(gè)函數(shù)的定義:

/**
 * Load bean definitions from the specified resource location.
 * <p>The location can also be a location pattern, provided that the
 * ResourceLoader of this bean definition reader is a ResourcePatternResolver.
 * @param location the resource location, to be loaded with the ResourceLoader
 * (or ResourcePatternResolver) of this bean definition reader
 * @param actualResources a Set to be filled with the actual Resource objects
 * that have been resolved during the loading process(要填充加載過(guò)程中已解析的實(shí)際資源對(duì)象*的集合). May be {@code null}
 * to indicate that the caller is not interested in those Resource objects.
 */
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {

解釋很清楚,這個(gè)location是指從指定資源路徑加載BeanDefinitions。

總結(jié)

從源碼可以看出從外部導(dǎo)入配置文件也就是給了通過(guò)一個(gè)總的配置文件來(lái)加載各個(gè)單一配置文件擴(kuò)展的機(jī)會(huì)。

以上就是Spring通過(guò)<import>標(biāo)簽導(dǎo)入外部配置文件的詳細(xì)內(nèi)容,更多關(guān)于Spring 導(dǎo)入外部配置文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:

相關(guān)文章

最新評(píng)論

昆山市| 成都市| 神池县| 古浪县| 淅川县| 增城市| 汨罗市| 华宁县| 淮北市| 西充县| 比如县| 汶上县| 青浦区| 喜德县| 报价| 凤城市| 寻甸| 德化县| 阿拉尔市| 彭山县| 阿尔山市| 凤山县| 秀山| 行唐县| 广德县| 老河口市| 会宁县| 奉贤区| 南京市| 南宫市| 略阳县| 峨山| 买车| 青海省| 文水县| 邢台县| 巴青县| 万安县| 彩票| 黄石市| SHOW|