Application context 和Resource 路径

4.7. Application context 和Resource 路径

  1. ClassPathResource:通过 ClassPathResource 以类路径的方式进行访问; 类路(classpath): 顾名思义,即类文件的输出路径。可通过Java Build Path -> Source -> Output folder/Default output folder 查看,如若是java 工程默认是bin ,若是web 工程默认是 classes。
  2. FileSystemResource:通过 FileSystemResource 以文件系统绝对路径相对路径的方式进行访问;                                  如:(1)绝对路径:Resource resource = context.getResource("file:c:/workspace/oms/config/applicationContext-ibatis.xml")。                                           (2)相对路径:但是如果使用相对路径要注意其根目录。例如在eclipse中,它的根目录就是你工程目录作为你的根目录。Resource resource = context.getResource("config/applicationContext-ibatis.xml")。                                             ...然后,由于使用的是XML文件,所以使用org.springframework.beans.factory.xml.XmlBeanFactory类,XmlBeanFactory实现了org.springframework.beans.factory.BeanFactory 接口,用来读取定义并建立BeanFactory实例。                       BeanFactory factory = new XmlBeanFactory(resource);    test aa = (test)factory.getBean("applicationListDao1");                            
  3. ServletContextResource:通过 ServletContextResource 以相对于Web应用根目录的方式进行访问。如:Resource resource = context.getResource("WEB-INF/conf/applicationContext-ibatis.xml")。 
  4. UrlResource :通过java.net.URL来访问资源,当然它也支持File格式,如“file:”

取得Resource接口的实例 后,可以使用getFile(),getInputStream()等方法来操作资源文件

Resource 接口的事例只是资源文件一个抽象代表,指定的资源有可能不存在,可以使用exists()进行测试。

 
先看一下Resource接口的定义:一下见这个连接:Spring中的Resource接口http://blog.csdn.net/myyate/archive/2007/10/10/1818714.aspx

定义文件存取:
 

Resource resource = new ClassPathResource("bean.xml");

BeanFactory factory = new XmlBeanFactory(resource);

HelloBean hello = (HelloBean) factory.getBean("helloBean");

这上面的ClassPathResource可以为FileSystemResource,InputStreamResource,ServletContextresource,URLResource;

  • 一个定义文件的载入,如下:

// bean.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC  "-//SPRING/DTD BEAN/EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

    <bean id="helloBeanOfJustin" class="onlyfun.caterpillar.HelloBean">

        <property name="helloWord"><value>Hello!Justin!</value></property>

    </bean>

    <bean id="helloBeanOfcaterpillar" class="onlyfun.caterpillar.HelloBean">

        <property name="helloWord"><value>Hello!caterpillar!</value></property>

    </bean>

</beans>

操作:

Resource resource = new ClassPathResource("bean.xml");

ListableBeanFactory factory = new XmlBeanFactory(resource);

Map helloBeans = factory.getBeansOfType(HelloBean.class, false, false);

  • 多个定义文件的载入:

BeanDefinitionRegistry reg = new DefaultListableBeanFactory();

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(reg);

//载入bean  

reader.loadBeanDefinitions(new ClassPathResource("bean1.xml"));

reader.loadBeanDefinitions(new ClassPathResource("bean2.xml"));

....

//取得Bean

BeanFactory bf = (BeanFactory) reg;

Object o = bf.getBean("helloBean");

需要org.springframework..beans.factory.support.BeanDefinitionRegistry

org.springframework..beans.factory.support.DefaultListableBeanFactory.XmlBeanDefinitionReader


     Spring的创始者Rod Johnson建议使用ApplicationContext 来取代BeanFactory,在实现ApplicationContext 的类中,最常使用的大概是一下三个。
    org.springframework.context.support.FileSystemXmlApplicationContext
可指定XML定义文件的相对路径或绝对路径来读去定义文件。
    org.springframework.context.support.ClassPathXmlApplicationContext
从Classpath设定路径中来读去定义文件。
    org.springframework.web.context.support.XmlWebApplicationContext
在Web应用程序的文件架构中,指定相对位置来读去定义文件。

4.7.1. 构造application context

 

 

    application context构造器通常使用字符串或字符串数组作为资源(比如组成context定义的XML文件)的定位路径。当这样的定位路径没有前缀时,指定的Resource 类型会通过这个路径来被创建并被用来载入bean的定义,这都取决于你所指定的application context。例如,如果你使用下面的代码来创建ClassPathXmlApplicationContext

ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");

这些Bean的定义会通过classpath载入并使用ClassPathResource。而如果你象下面这么创建FileSystemXmlApplicationContext

ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");

这些Bean的定义会通过文件系统从相对于当前工作目录中被载入并使用FileSystemResource

请注意如果定位路径使用classpath前缀或标准的URL前缀,那它就会覆盖默认的Resource 类型(FileSystemResource)。因此下面的FileSystemXmlApplicationContext...

ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");

...实际上会通过classpath载入其bean定义。然而它仍是个FileSystemXmlApplicationContext。如果后面它被当作ResourceLoader 来使用,那么任何没有使用前缀的路径依然会被当作一个文件系统路径。

 

4.7.1.1. 创建 ClassPathXmlApplicationContext 实例 - 简介

     ClassPathXmlApplicationContext 提供了多种构造方法以便于初始化。但其核心是,如果我们仅仅提供由XML文件名组成的字符串数组(没有完整路径信息),而且提供了Class;那么该ClassPathXmlApplicationContext就会从给定的类中抽取路径信息。

希望通过一个示例把这些阐述清楚。假设有这样的目录结构:

 com/
  foo/
        services.xml
        daos.xml
        MessengerService.class

'services.xml''daos.xml' 中定义的bean组成的 ClassPathXmlApplicationContext 实例会象这样地来实例化...

ApplicationContext ctx = new ClassPathXmlApplicationContext(
    new String[] {"services.xml", "daos.xml"}, MessengerService.class);

欲了解 ClassPathXmlApplicationContext 多种构造方法的细节,请参考它的Javadocs。

4.7.2. Application context构造器中资源路径的通配符

     Application context构造器中资源路径的值可以是简单的路径(就像上面的那样),即一对一映射到一个目标资源;或者可以包含特殊的"classpath*:"前缀Ant风格的正则表达式(用Spring的 PathMatcher 工具来匹配)。后面的二者都可以使用通配符。

该机制的一个用处就是做组件类型的应用组装。所有的组件都可以用通用的定位路径“发布”context定义片断,这样当使用相同的 classpath*: 前缀创建最终的application context时,所有的组件片断都会被自动装入。

     请注意,这个通配符只在application context构造器的资源路径中 (或直接在类的层次中使用 PathMatcher 工具时)有效,它会在构造时进行解析。这与 Resource 类型本身没有关联。因为同一时刻只能指向一个资源,所以不能使用 classpath*: 前缀来构造实际的Resource。<也就是不能在像这样语句中使用classpath*:前缀, Resource resource = context.getResource("WEB-INF/conf/applicationContext-ibatis.xml")。是否?>

4.7.2.1. Ant风格的pattern

在包含Ant风格的pattern时,例如:

     /WEB-INFapplicationContext.xml
     file:C:/some/pathapplicationContext.xml

解析器会进行一个预先定义的复杂的过程去试图解析通配符。它根据路径中最后一个非通配符片断产生一个Resource并从中获得一个URL。如果这个URL不是一个"jar:" URL或特定容器的变量(例如WebLogic中的 "zip:",WebSphere中的"wsjar"等等), 那么可以从中获得一个java.io.File,并用它从文件系统中解析通配符。如果是一个jar URL,解析器可以从中取得一个 java.net.JarURLConnection,或者手工解析该jar URL, 随后遍历jar文件以解析通配符。

4.7.2.1.1. 潜在的可移植性

如果给定的路径已经是一个文件URL(可以是显式的或者是隐式的),由于基本的ResourceLoader是针对文件系统的,那么通配符一定能够移植。

如果给定的路径是一个classpath的位置,那么解析器必须通过一个 Classloader.getResource() 调用获得最后一个非通配符路径片断的URL。因为这仅仅是一个路径的节点(不是最终的文件),所以它并未确切定义(在 ClassLoader Javadocs里) 此处究竟会返回什么类型的URL。一般情况下,当classpath资源解析为一个文件系统位置时,返回一个代表目录的 java.io.File;当解析为jar位置时,返回某类jar URL。当然,这个操作涉及到可移植性。

如果从最后一个非通配符片断中获得一个jar URL,那么解析器一定能从中取得一个 java.net.JarURLConnection,或者手动解析jar URL以遍历jar文件,从而解析通配符。这一操作在大多数环境中能正常工作,不过也有例外,因此我们强烈建议特定环境中的jar资源通配符解析应在正式使用前要经过彻底测试。

《续》

4.7.2.2. classpath*: 前缀

当构造基于XML的application context时,路径字符串可能使用特殊的 classpath*: 前缀:

ApplicationContext ctx =
    new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");

此前缀表示所有与给定名称匹配的classpath资源都应该被获取(其中,这经常会在调用 ClassLoader.getResources(...)) 时发生),并接着将那些资源全并成最终的application context定义。

Classpath*: 的可移植性

带通配符的classpath依赖于底层classloader的 getResources() 方法。现在大多数的应用服务器提供自己的classloader实现,它们在处理jar文件时的行为也许会有所不同。要测试 classpath*: 是否有效,可以简单地用classloader从classpath中的jar文件里加载一个文件: getClass().getClassLoader().getResources("<someFileInsideTheJar>")。针对两个不同位置但有相同名字的文件来运行测试。如果结果不对,那么就查看一下应用服务器的文档,特别是那些可能影响classloader行为的设置。

"classpath*:"前缀也能在位置路径的其他部分结合PathMatcher pattern一起使用,例如"classpath*:META-INFservice-context.xml

解析器会排除getResource("com/mycompany");返回的(第一个)URL。如果这个基础包节点存在于多个classloader位置,最终要找的资源未必会被发现。因此在这种情况中最好在这个Ant风格的pattern中使用"classpath*:",这样就会搜索包含根包在内所有类路径。

4.7.3.  FileSystemResource 提示

一个并没有与 FileSystemApplicationContext 绑定的 FileSystemResource(也就是说FileSystemApplicationContext 并不是真正的ResourceLoader),会象你期望的那样分辨绝对和相对路径。相对路径是相对于当前的工作目录,而绝对路径是相对与文件系统的根目录。

为了向前兼容的目的,当 FileSystemApplicationContext 是个 ResourceLoader 时它会发生变化。FileSystemApplicationContext 会简单地让所有绑定的 FileSystemResource 实例把绝对路径都当成相对路径,而不管它们是否以反斜杠开头。也就是说,下面的含义是相同的:

ApplicationContext ctx =
    new FileSystemClassPathXmlApplicationContext("conf/context.xml");
ApplicationContext ctx =
    new FileSystemClassPathXmlApplicationContext("/conf/context.xml");

下面的也一样:(虽然把它们区分开来也很有意义,但其中的一个是相对路径而另一个则是绝对路径)。

FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("some/resource/path/myTemplate.txt");
FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("/some/resource/path/myTemplate.txt");

实际上如果的确需要使用绝对路径,那你最好就不要使用 FileSystemResourceFileSystemXmlApplicationContext来确定绝对路径。我们可以通过使用 file: URL前缀来强制使用UrlResource

// actual context type doesn't matter, the Resource will always be UrlResource
ctx.getResource("file:/some/resource/path/myTemplate.txt");
// force this FileSystemXmlApplicationContext to load it's definition via a UrlResource
ApplicationContext ctx =
    new FileSystemXmlApplicationContext("file:/conf/context.xml");
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值