8.3.4 在ApplicationContext中使用资源

8.3.4 在ApplicationContext中使用资源

不管以怎样的方式创建ApplicationContext实例,都需要为ApplicationContext指定配置文件, Spring允许使用一份或多份XML配置文件。
当程序创建ApplicationContext实例时,通常也是以Resource的方式来访问配置文件的,所以ApplicationContext完全支持ClassPathResource, FileSystemResourceServletContextResource等资源访问方式。 ApplicationContext确定资源访问策略通常有两种方法。

  1. 使用ApplicationContext实现类指定访问策略。
  2. 使用前缀指定访问策略。

1. 使用ApplicationContext实现类指定访问策略

创建ApplicationContext对象时,通常可以使用如下三个实现类。

ApplicationContext实现类 对应的Resource实现类
ClassPathXmlApplicatinContext 对应使用ClassPathResource进行资源访问。
FileSystemXmlApplicationContext 对应使用FileSystemResoure进行资源访问
XmlWebApplicationContext 对应使用ServletContextResource进行资源访问。

从上面的说明可以看出,当使用ApplicationContext的不同实现类时,就意味着Spring使用相应的资源访问策略。
当使用如下代码来创建Spring容器时,则意味着从本地文件系统来加载XML配置文件。

1
2
//从本地文件系统的当前路径加载 beans.xml文件创建Spring容器
ApplicationContext ctx=new FileSystemXmlApplicationContext("beans.xml");

程序从本地文件系统的当前路径下读取beans.xml文件,然后加载该资源,并根据该配置文件来创建ApplicationContext实例。相应的,采用ClassPathApplicationContext实现类,则从类加载路径下加载XML配置文件.

PS:据我观察当前路径默认是项目的跟路径,类加载路径默认是src目录的路径

2. 使用前缀指定访问策略

Spring也允许使用前缀来指定资源访问策略,例如,采用如下代码来创建ApplicationContext:

1
2
ApplicationContext ctx=new
FileSystemXmlApplicationContext("classpath:beans.xml");

虽然上面的代码采用了FileSystemXmlApplicationContext实现类,但程序依然从类加载路径下搜索beans.xml配置文件,而不是从本地文件系统的当前路径下搜索。相应的,还可以使用http:,ftp:等前缀,用来确定对应的资源访问策略。
看如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package lee;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.Resource;

public class SpringTest
{
public static void main(String[] args) throws Exception
{
@SuppressWarnings("resource")
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"classpath:beans.xml");
System.out.println(ctx);
// 使用ApplicationContext的资源访问策略来访问资源,没有指定前缀
Resource r = ctx.getResource("book.xml");
System.out.println(r.getClass());
System.out.println(r.getDescription());
}
}

Resource实例的输出结果是:

1
2
3
org.springframework.context.support.FileSystemXmlApplicationContext@439f5b3d, started on Tue Sep 03 00:36:36 CST 2019
class org.springframework.core.io.FileSystemResource
file [E:\workspace_QingLiangJiJavaEEQiYeYingYongShiZhang5\ApplicationContext\book.xml]

上面程序中创建Spring容器时,系统将从类加载路径下搜索beans.xml;但使用ApplicationContext来访问资源时,依然采用的是FileSystemResource实现类,这与FileSystemXmlApplicationContext的访问策略是一致的。

classpath:前缀指定资源访问策略仅仅对当次访问有效

这表明:通过classpath:前缀指定资源访问策略仅仅对当次访问有效,程序后面进行资源访问时,还是会根据AppliactionContext的实现类来选择对应的资源访问策略.

ApplicationContext访问资源时建议显示采用对应实现类来加载配置文件

因此,如果程序需要使用ApplicationContext访问资源,建议显式采用对应的实现类来加载配置文件,而不是通过前缀来指定资源访问策略。当然,也可在每次进行资源访问时都指定前缀,让程序根据前缀来选择资源访问策略。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package lee;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.Resource;

public class SpringTest
{
public static void main(String[] args) throws Exception
{
@SuppressWarnings("resource")
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"classpath*:beans.xml");
System.out.println(ctx);
// 使用ApplicationContext的资源访问策略来访问资源,通过 classpath:前缀指定策略
Resource r = ctx.getResource("classpath:book.xml");
System.out.println(r.getClass());
System.out.println(r.getDescription());
}
}

运行结果:

1
2
3
org.springframework.context.support.FileSystemXmlApplicationContext@439f5b3d, started on Tue Sep 03 00:40:59 CST 2019
class org.springframework.core.io.ClassPathResource
class path resource [book.xml]

由此可见,如果每次进行资源访问时都指定了前缀,则系统会采用前缀相应的资源访问策略

3. classpath*:前缀的用法

classpath*:前缀提供了加载多个XML配置文件的能力,当使用classpath*:前缀来指定XML配置文件时,系统将搜索类加载路径,找出所有与文件名匹配的文件,分别加载文件中的配置定义,最后合并成一个ApplicationContext。看如下代码:

将配置文件beans.xml分别放在应用的classes路径(该路径被设为类加载路径之一)下,并将配置文件放在classes/aa路径下(该路径也被设为类加载路径之一),程序实例化ApplicationContext时显示:

从上面的执行结果可以看出,当使用classpath*:前缀时, Spring将会搜索类加载路径下所有满足该规则的配置文件。
如果不是采用classpath*:前缀,而是改为使用classpath:前缀, Spring则只加载第一个符合条件的XML文件。例如如下代码:

1
2
ApplicationContext ctx=
new FileSystemXmlApplicationContext("classpath:beans.xml");