스프링 도큐먼트 읽고 정리해보기 / Version 5.1.9.RELEASE


2. Resources

2.1 Introduction

리소스에 관한 자바의 표준은 java.net.URL 클래스이고 URL prefix에 따라서 다양한 핸들러들이 존재한다. 하지만 클래스패스로부터 리소스에 접근하는 표준화된 URL 구현체의 부재나 URL 인터페이스가 갖는 기능적인 부족함들이 존재한다.

 

2.2 The Resource Interface

스프링에서는 이러한 단점을 보완하여 Resource 접근에 대해 추상화한 org.springframework.core.io.Resource 인터페이스를 제공한다. (기존의 java.net.URL 을 감싼 형태이다.)

public interface Resource extends InputStreamSource {

    boolean exists();

    boolean isOpen();

    URL getURL() throws IOException;

    File getFile() throws IOException;

    Resource createRelative(String relativePath) throws IOException;

    String getFilename();

    String getDescription();

}

InputStreamSource 인터페이스를 상속받아 리소스의 inputStream을 가져올 수 있는 InputStreamSoure.getInputStream() 메서드를 제공하며, exists() 등 추가 기능을 제공한다.

 

2.3 Built-in Resource Implementations

스프링은 추상화한 Resource 인터페이스의 구현체를 제공하고 있다.

  • UrlResource
    java.net.URL 을 감싼 형태로 URL을 이용하여 리소스에 접근한다. 파일시스템에 접근하기 위한 file: 이나 HTTP 프로토콜을 이용하여 접근하는 http: , FTP 프로토콜을 이용하는 ftp: 같이 접두어를 통해 접근방식을 정한다.
  • ClassPathResource
    classpath 상에 존재하는 리소스에 대한 접근을 위한 리소스 구현체이다. 명시적으로 ClassPathResource 생성자를 이용하여 생성할 수도 있고, 문자열에 classpath: 접두어로 생성될 수도 있다.
  • FileSystemResource
  • ServletContextResource 웹 어플리케이션 루트에서 상대경로로 리소스를 찾는 구현체이다.
  • InputStreamResource
  • ByteArrayResource

 

2.4 The ResourceLoader

ResourceLoader 인터페이스는 Resource 인스턴스를 리턴받기 위한 용도로 사용한다.

public interface ResourceLoader { 
    Resource getResource(String location);
}

ApplicationContext는 ResourceLoader를 구현하고 있으므로 ApplicationContext를 이용하여 리소스를 리턴받을 수 있다.

ApplicationContext extends ResourcePatternResolver
ResourcePatternResolver extends ResourceLoader

ApplicationContext도 인터페이스이기 때문에 어떤 ApplicationContext 구현체에게 getResource()를 호출하느냐에 따라 리턴되는 Resource의 구현체가 달라진다. 예를 들어, ClassPathXmlApplicationContext에서 getResource()를 호출한다면 ClassPathResource가 리턴된다. 이러한 식으로 ApplicationContext와 리턴되는 Resource의 타입은 맵핑된다.

 

FileSystemXmlApplicationContext- FileSystemResource

WebApplicationContext - ServletContextResource

 

만일 ApplicationContext 구현체의 타입에 상관없이 특정 타입의 Resource를 리턴받고 싶다면 getResource()에 대한 문자열 인자에 Prefix를 부여하면 된다.

// ClassPathResource 리턴
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");

// FileSystemResource 리턴
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");

// UrlResource 리턴
Resource template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");

정리하자면, ResourceLoader로부터 리턴받는 Resource의 타입은 ApplicationContext의 구현체의 타입에 따라 다르며, 특정 타입의 Resource를 리턴받고자 할 때는 문자열 인자에 알맞은 prefix를 부여하면 된다.

 

2.5 The ResourceLoaderAware interface

ResourceLoaderAware는 콜백 인터페이스로 컨텍스트에 생성된 ResourceLoader 빈을 가져올 수 있다.

public interface ResourceLoaderAware {
    void setResourceLoader(ResourceLoader resourceLoader);
}

물론 ApplicationContext가 ResourceLoader를 구현하고 있기 때문에 ApplicationContextAware로 컨텍스트를 이용하여 리소스에 접근할 수 있지만, 추천되지는 않는다. 해당 빈을 가져오고자 하는 이유가 리소스의 접근이라면 그 용도로 설계된 ResourceLoader 타입의 빈을 가져오는 것이 맞다.

2.6 Resources as Dependencies

만일 특정 빈이 고정된(static) 리소스를 필요로 한다면 프로퍼티로써 ResourceLoader를 사용하지 않고 Resource 빈을 주입할 수 있다. 예시처럼 value속성을 문자열로 주지만 Resource로 빈 주입이 가능한 것은 ApplicationContext가 등록하고 사용하는 특별한 JavaBean인 PropertyEditor가 있기 때문이다.

<bean id="myBean" class="...">
    <property name="template1" value="some/resource/path/myTemplate.txt"/>
    <property name="template2" value="classpath:some/resource/path/myTemplate.txt">
    <property name="template3" value="file:///some/resource/path/myTemplate.txt"/>
</bean>

 

2.7 Application Contexts and Resource Paths

XML을 베이스로 한 ApplicationContext를 생성시 Resource를 활용하는 방법에 대해 알아본다.

  • ApplicationContext 생성시 Resource 인자

    ApplicationContext을 소스코드로 생성자를 이용하여 생성할 때 인자로 문자열(String)을 지정한다. 문자열이 해석되어 특정 타입의 Resource객체로 XML파일이 로드된다. 문자열에 prefix를 지정하지 않으면 ApplicationContext의 구현체 타입에 따라 Resource의 타입이 결정되어 로드한다.

// ClassPathResource로 빈 설정파일이 로드된다.
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");

// FileSystemResource로 빈 설정파일이 로드된다.
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");

 

  • ApplicationContext 생성시 와일드카드(*) 사용

    와일드카드를 이용하여 Ant-Style Patterns을 활용할 수 있다.

/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml

      또는 classpath*: prefix를 활용할 수 있다.

// classpath에서 해당 이름의 모든 xml이 로드된다.
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");

      Ant-Style과 classpath*: prefix를 혼용하여 사용할 수도 있다.

 

  • FileSystemResource를 사용할 때 주의점 FileSystemApplicationContext는 모든 FileSystemResource 인스턴스들에 대해서 슬래쉬(/)의 유무에 상관없이 상대경로를 사용하도록 강제한다. 즉 아래 예시는 동일하게 상대경로를 지정한다.

// 1번
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/context.xml");

// 2번
ApplicationContext ctx = new FileSystemXmlApplicationContext("/conf/context.xml");

      그러므로 만일 절대경로를 사용하고 싶으면 file:/// prefix를 활용하여 UrlResource를 사용하도록 한다.

// force this FileSystemXmlApplicationContext to load its definition via a UrlResource
ApplicationContext ctx = new FileSystemXmlApplicationContext("file:///conf/context.xml");

// actual context type doesn't matter, the Resource will always be UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt");

+ Recent posts