Loading...
Spring Framework Reference Documentation 7.0.2의 Resources의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
이 장에서는 Spring이 resource를 어떻게 처리하는지와 Spring에서 resource를 다루는 방법을 설명합니다. 다음 주제를 포함합니다:
Resource InterfaceResource ImplementationsResourceLoader InterfaceResourcePatternResolver InterfaceResourceLoaderAware InterfaceJava의 표준 java.net.URL class와 다양한 URL prefix에 대한 표준 handler는 불행히도 모든 low-level resource 접근에 충분히 적합하지 않습니다. 예를 들어, classpath로부터 또는 ServletContext를 기준으로 얻어야 하는 resource에 접근하는 데 사용할 수 있는 표준화된 URL 구현이 없습니다.
특수한 URL prefix(예: http: 같은 기존 prefix에 대한 handler와 유사)에 대해 새로운 handler를 등록하는 것은 가능하지만, 일반적으로 상당히 복잡하며, URL interface는 여전히 가리키는 resource의 존재를 확인하는 메서드와 같은 바람직한 기능이 일부 부족합니다.
Resource Interfaceorg.springframework.core.io. package에 위치한 Spring의 Resource interface는 low-level resource에 대한 접근을 추상화하기 위한 보다 능력 있는 interface를 목표로 합니다. 다음 목록은 Resource interface에 대한 개요를 제공합니다. 자세한 내용은 Resource javadoc을 참조하십시오.
1public interface Resource extends InputStreamSource { 2 3 boolean exists(); 4 5 boolean isReadable(); 6 7 boolean isOpen(); 8 9 boolean isFile(); 10 11 URL getURL() throws IOException; 12 13 URI getURI() throws IOException; 14 15 File getFile() throws IOException; 16 17 ReadableByteChannel readableChannel() throws IOException; 18 19 long contentLength() throws IOException; 20 21 long lastModified() throws IOException; 22 23 Resource createRelative(String relativePath) throws IOException; 24 25 String getFilename(); 26 27 String getDescription(); 28}
Resource interface의 정의에서 볼 수 있듯이, 이 interface는 InputStreamSource interface를 확장합니다. 다음 목록은 InputStreamSource interface의 정의를 보여 줍니다:
1public interface InputStreamSource { 2 3 InputStream getInputStream() throws IOException; 4}
Resource interface에서 가장 중요한 메서드들은 다음과 같습니다:
getInputStream(): resource를 찾고 열어 resource로부터 읽기 위한 InputStream을 반환합니다. 각 호출 시 새로운 InputStream을 반환하는 것이 기대됩니다. stream을 닫는 책임은 호출자에게 있습니다.exists(): 이 resource가 실제 물리적 형태로 존재하는지를 나타내는 boolean을 반환합니다.isOpen(): 이 resource가 열린 stream을 가진 handle을 나타내는지를 나타내는 boolean을 반환합니다. true인 경우 InputStream은 여러 번 읽을 수 없으며, resource leak을 피하기 위해 한 번만 읽고 닫아야 합니다. 일반적인 resource 구현에서는 모두 false를 반환하며, InputStreamResource는 예외입니다.getDescription(): resource를 사용할 때 error 출력을 위해 사용되는 이 resource에 대한 설명을 반환합니다. 이는 종종 완전한 file 이름이나 resource의 실제 URL입니다.다른 메서드들을 사용하면 resource를 나타내는 실제 URL이나 File 객체를 얻을 수 있습니다(기저 구현이 호환되고 해당 기능을 지원하는 경우).
Resource interface의 일부 구현은 쓰기를 지원하는 resource를 위해 확장된 WritableResource interface도 구현합니다.
Spring 자체는 resource가 필요할 때 많은 메서드 시그니처에서 argument type으로 Resource abstraction을 광범위하게 사용합니다. 일부 Spring API의 다른 메서드(예: 다양한 ApplicationContext 구현에 대한 생성자)는 String을 받는데, 단순한 형태 또는 adorn되지 않은 형태의 String은 해당 context 구현에 적합한 Resource를 생성하는 데 사용되거나, String path에 특수 prefix를 사용하여 호출자가 특정 Resource 구현이 생성 및 사용되어야 함을 지정할 수 있습니다.
Resource interface는 Spring과 함께, 그리고 Spring에 의해 많이 사용되지만, 실제로는 여러분의 코드에서 resource에 접근하기 위한 일반 유틸리티 클래스로 자체적으로 사용하는 것도 매우 편리합니다. 여러분의 코드가 Spring의 다른 부분을 알거나 신경 쓰지 않더라도 말입니다.
이것은 여러분의 코드를 Spring에 결합시키긴 하지만, 실제로는 이 작은 유틸리티 클래스 집합에만 결합시키는 것이며, 이는 URL의 보다 능력 있는 대체물로 사용되며 이 목적을 위해 사용할 다른 라이브러리와 동등한 것으로 간주할 수 있습니다.
Resourceabstraction은 기능을 대체하지 않습니다. 가능한 경우 이를 wrapping합니다. 예를 들어,UrlResource는 URL을 wrapping하고 작업을 수행하기 위해 wrapping된URL을 사용합니다.
Resource ImplementationsSpring에는 여러 가지 built-in Resource 구현이 포함되어 있습니다:
UrlResourceClassPathResourceFileSystemResourcePathResourceServletContextResourceInputStreamResourceByteArrayResourceSpring에서 사용 가능한 Resource 구현의 전체 목록은 Resource javadoc의 "All Known Implementing Classes" 섹션을 참조하십시오.
UrlResourceUrlResource는 java.net.URL을 wrapping하며, file, HTTPS 대상, FTP 대상 등 일반적으로 URL로 접근 가능한 모든 객체에 접근하는 데 사용할 수 있습니다. 모든 URL은 표준화된 String 표현을 가지며, 적절한 표준화된 prefix가 사용되어 한 URL type을 다른 URL type과 구분합니다.
여기에는 filesystem path에 접근하기 위한 file:, HTTPS 프로토콜을 통해 resource에 접근하기 위한 https:, FTP를 통해 resource에 접근하기 위한 ftp: 등이 포함됩니다.
UrlResource는 Java 코드에서 UrlResource 생성자를 명시적으로 사용하여 생성되지만, path를 나타내기 위한 String argument를 받는 API 메서드를 호출할 때 종종 암묵적으로 생성됩니다.
후자의 경우, JavaBeans PropertyEditor가 최종적으로 어떤 type의 Resource를 생성할지 결정합니다. path string에 (classpath:와 같은) 잘 알려진 prefix(property editor에 잘 알려진)가 포함되어 있으면, 해당 prefix에 적합한 specialized Resource를 생성합니다. 그러나 prefix를 인식하지 못하면, 해당 string을 표준 URL string으로 간주하고 UrlResource를 생성합니다.
ClassPathResource이 class는 classpath로부터 얻어야 하는 resource를 나타냅니다. 이는 thread context class loader, 주어진 class loader 또는 resource를 로딩하기 위한 주어진 class를 사용합니다.
이 Resource 구현은 class path resource가 filesystem에 존재하는 경우 java.io.File로서의 resolution을 지원하지만, servlet 엔진 또는 환경이 무엇이든 jar에 존재하며 filesystem으로 확장되지 않은 classpath resource에 대해서는 지원하지 않습니다. 이를 해결하기 위해 다양한 Resource 구현은 항상 java.net.URL로서의 resolution을 지원합니다.
ClassPathResource는 Java 코드에서 ClassPathResource 생성자를 명시적으로 사용하여 생성되지만, path를 나타내기 위한 String argument를 받는 API 메서드를 호출할 때 종종 암묵적으로 생성됩니다. 후자의 경우, JavaBeans PropertyEditor는 string path에서 특수 prefix인 classpath:를 인식하고, 이 경우 ClassPathResource를 생성합니다.
FileSystemResource이는 java.io.File handle을 위한 Resource 구현입니다. 또한 java.nio.file.Path handle도 지원하며, Spring의 표준 String 기반 path 변환을 적용하지만 모든 작업은 java.nio.file.Files API를 통해 수행합니다. 순수하게 java.nio.path.Path 기반 지원을 위해서는 대신 PathResource를 사용하십시오. FileSystemResource는 File 및 URL로서의 resolution을 지원합니다.
PathResource이는 java.nio.file.Path handle을 위한 Resource 구현으로, 모든 작업과 변환을 Path API를 통해 수행합니다. File 및 URL로서의 resolution을 지원하며, 확장된 WritableResource interface도 구현합니다. PathResource는 사실상 FileSystemResource에 대한 순수 java.nio.path.Path 기반 대안으로, 다른 createRelative 동작을 가집니다.
ServletContextResource이는 관련 web 애플리케이션의 root 디렉터리 내에서 relative path를 해석하는 ServletContext resource를 위한 Resource 구현입니다.
항상 stream access와 URL access를 지원하지만, web 애플리케이션 archive가 확장되어 resource가 실제로 filesystem에 존재하는 경우에만 java.io.File access를 허용합니다. 그것이 filesystem으로 확장되어 있는지, 아니면 classpath의 JAR에서 직접 접근되는지, 혹은 database와 같은 다른 곳(가능한 시나리오)에서 접근되는지는 실제로 Servlet 컨테이너에 따라 달라집니다.
InputStreamResourceInputStreamResource는 주어진 InputStream을 위한 Resource 구현입니다. 특정 Resource 구현이 적용되지 않는 경우에만 사용해야 합니다. 특히, 가능한 경우 ByteArrayResource나 file 기반 Resource 구현 중 하나를 사용하는 것이 좋습니다.
다른 Resource 구현과 달리, 이는 이미 열린 resource에 대한 descriptor입니다. 따라서 isOpen()에서 true를 반환합니다. resource descriptor를 어딘가에 보관해야 하거나 stream을 여러 번 읽어야 하는 경우에는 이를 사용하지 마십시오.
ByteArrayResource이는 주어진 byte array를 위한 Resource 구현입니다. 주어진 byte array에 대해 ByteArrayInputStream을 생성합니다.
단일 사용 InputStreamResource를 사용하지 않고도 주어진 byte array로부터 content를 로딩하는 데 유용합니다.
ResourceLoader InterfaceResourceLoader interface는 Resource 인스턴스를 반환(즉, 로드)할 수 있는 객체가 구현하도록 설계되었습니다. 다음 목록은 ResourceLoader interface 정의를 보여 줍니다:
1public interface ResourceLoader { 2 3 Resource getResource(String location); 4 5 ClassLoader getClassLoader(); 6}
모든 애플리케이션 context는 ResourceLoader interface를 구현합니다. 따라서 모든 애플리케이션 context는 Resource 인스턴스를 얻는 데 사용할 수 있습니다.
특정 애플리케이션 context에서 getResource()를 호출하고, 지정된 location path에 특정 prefix가 없는 경우, 해당 애플리케이션 context에 적합한 type의 Resource를 돌려받게 됩니다. 예를 들어, 다음 코드 snippet이 ClassPathXmlApplicationContext 인스턴스에 대해 실행된다고 가정해 봅시다:
1Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
1val template = ctx.getResource("some/resource/path/myTemplate.txt")
ClassPathXmlApplicationContext에 대해서는, 이 코드는 ClassPathResource를 반환합니다. 동일한 메서드가 FileSystemXmlApplicationContext 인스턴스에 대해 실행되면, FileSystemResource를 반환합니다. WebApplicationContext에 대해서는 ServletContextResource를 반환합니다. 각 context에 대해 유사하게 적절한 객체를 반환합니다.
그 결과, 특정 애플리케이션 context에 적합한 방식으로 resource를 로드할 수 있습니다.
반면, 다음 예제에서 보이듯이, 특수 prefix인 classpath:를 지정하여 애플리케이션 context type에 관계없이 ClassPathResource가 사용되도록 강제할 수도 있습니다:
1Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
1val template = ctx.getResource("classpath:some/resource/path/myTemplate.txt")
유사하게, 표준 java.net.URL prefix 중 어느 것이든 지정하여 UrlResource가 사용되도록 강제할 수 있습니다. 다음 예제는 file과 https prefix를 사용합니다:
1Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
1val template = ctx.getResource("file:///some/resource/path/myTemplate.txt")
1Resource template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");
1val template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt")
다음 표는 String 객체를 Resource 객체로 변환하는 전략을 요약합니다:
| Prefix | Example | Explanation |
|---|---|---|
| classpath: | classpath:com/myapp/config.xml | classpath에서 로딩됩니다. |
| file: | file:///data/config.xml | filesystem에서 URL로 로딩됩니다. FileSystemResource Caveats도 참조하십시오. |
| https: | https://myserver/logo.png | URL로 로딩됩니다. |
| (none) | /data/config.xml | 기반이 되는 ApplicationContext에 따라 달라집니다. |
Table 1. Resource string
ResourcePatternResolver InterfaceResourcePatternResolver interface는 ResourceLoader interface의 확장으로, location pattern(예: Ant-style path pattern)을 Resource 객체로 resolve하는 전략을 정의합니다.
1public interface ResourcePatternResolver extends ResourceLoader { 2 3 String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; 4 5 Resource[] getResources(String locationPattern) throws IOException; 6}
위에서 볼 수 있듯이, 이 interface는 또한 class path에서 일치하는 모든 resource를 위한 특수 classpath*: resource prefix를 정의합니다. 이 경우 resource location은 placeholder가 없는 path여야 한다는 점에 유의하십시오. 예를 들어, classpath*:/config/beans.xml과 같습니다.
class path의 JAR file이나 서로 다른 디렉터리는 동일한 path와 동일한 이름을 가진 여러 file을 포함할 수 있습니다. classpath*: resource prefix를 사용한 wildcard 지원에 대한 자세한 내용은 Wildcards in Application Context Constructor Resource Paths 및 해당 하위 섹션을 참조하십시오.
전달된 ResourceLoader(예: ResourceLoaderAware semantics를 통해 제공된 것)는 이 확장 interface도 구현하는지 여부를 확인할 수 있습니다.
PathMatchingResourcePatternResolver는 ApplicationContext 외부에서 사용 가능하며 ResourceArrayPropertyEditor에 의해 Resource[] bean property를 채우는 데 사용되는 standalone 구현입니다. PathMatchingResourcePatternResolver는 지정된 resource location path를 하나 이상의 일치하는 Resource 객체로 resolve할 수 있습니다.
source path는 target Resource에 대한 one-to-one mapping을 가지는 simple path일 수도 있고, 또는 특수 classpath*: prefix 및/또는 internal Ant-style 정규 표현식(Spring의 org.springframework.util.AntPathMatcher 유틸리티를 사용하여 match)을 포함할 수도 있습니다. 후자의 두 가지는 사실상 wildcard입니다.
모든 표준
ApplicationContext의 기본ResourceLoader는 실제로ResourcePatternResolverinterface를 구현하는PathMatchingResourcePatternResolver의 인스턴스입니다. 동일한 내용은 기본PathMatchingResourcePatternResolver에 delegate하는ResourcePatternResolverinterface를 구현하는ApplicationContext인스턴스 자체에도 적용됩니다.
ResourceLoaderAware InterfaceResourceLoaderAware interface는 ResourceLoader reference가 제공되기를 기대하는 컴포넌트를 식별하는 특수 callback interface입니다. 다음 목록은 ResourceLoaderAware interface의 정의를 보여 줍니다:
1public interface ResourceLoaderAware { 2 3 void setResourceLoader(ResourceLoader resourceLoader); 4}
class가 ResourceLoaderAware를 구현하고 애플리케이션 context(Spring이 관리하는 bean으로서)에 배포되면, 애플리케이션 context는 이를 ResourceLoaderAware로 인식합니다. 그런 다음 애플리케이션 context는 setResourceLoader(ResourceLoader)를 호출하고, 자신을 argument로 제공합니다(기억하십시오. Spring의 모든 애플리케이션 context는 ResourceLoader interface를 구현합니다).
ApplicationContext는 ResourceLoader이므로, bean은 ApplicationContextAware interface를 구현하고 제공된 애플리케이션 context를 직접 사용하여 resource를 로드할 수도 있습니다. 그러나 일반적으로, 그것이 필요한 전부라면 specialized ResourceLoader interface를 사용하는 것이 더 좋습니다. 코드는 resource 로딩 interface(유틸리티 interface로 간주될 수 있음)에만 결합되고 전체 Spring ApplicationContext interface에는 결합되지 않습니다.
애플리케이션 컴포넌트에서는 ResourceLoaderAware interface를 구현하는 대신 ResourceLoader의 autowiring에 의존할 수도 있습니다. Autowiring Collaborators에 설명된 traditional constructor 및 byType autowiring mode는 각각 생성자 argument나 setter 메서드 parameter에 대해 ResourceLoader를 제공할 수 있습니다.
더 큰 유연성(여러 parameter 메서드와 field autowiring 기능 포함)을 위해서는 annotation 기반 autowiring 기능 사용을 고려하십시오. 이 경우, field, 생성자 argument 또는 메서드 parameter가 ResourceLoader type을 기대하고 해당 field, 생성자 또는 메서드에 @Autowired annotation이 있는 한, ResourceLoader는 해당 위치에 autowired됩니다. 자세한 내용은 Using @Autowired를 참조하십시오.
wildcard를 포함하거나 특수
classpath*:resource prefix를 사용하는 resource path에 대해 하나 이상의Resource객체를 로드하려면, 애플리케이션 컴포넌트에ResourceLoader대신ResourcePatternResolver의 인스턴스가 autowired되도록 고려하십시오.
bean 자체가 어떤 종류의 동적 프로세스를 통해 resource path를 결정하고 제공하려는 경우, bean이 resource를 로드하기 위해 ResourceLoader 또는 ResourcePatternResolver interface를 사용하는 것이 타당할 수 있습니다. 예를 들어, 필요한 특정 resource가 사용자의 role에 따라 달라지는 template의 로딩을 고려해 보십시오.
resource가 static이라면, ResourceLoader interface(또는 ResourcePatternResolver interface)의 사용을 완전히 제거하고, bean이 필요한 Resource 프로퍼티를 노출하게 한 다음, 해당 프로퍼티가 bean에 주입되도록 하는 것이 타당합니다.
이러한 프로퍼티를 주입하는 것을 사소하게 만드는 것은 모든 애플리케이션 context가 String path를 Resource 객체로 변환할 수 있는 특수 JavaBeans PropertyEditor를 등록하고 사용한다는 점입니다. 예를 들어, 다음 MyBean class는 type이 Resource인 template 프로퍼티를 가집니다.
1public class MyBean { 2 3 private Resource template; 4 5 public setTemplate(Resource template) { 6 this.template = template; 7 } 8 9 // ... 10}
1class MyBean(var template: Resource)
XML 설정 file에서, 다음 예제에서 보이듯이 template 프로퍼티는 해당 resource에 대한 simple string으로 설정할 수 있습니다:
1<bean id="myBean" class="example.MyBean"> 2 <property name="template" value="some/resource/path/myTemplate.txt"/> 3</bean>
resource path에는 prefix가 없다는 점에 유의하십시오. 따라서 애플리케이션 context 자체가 ResourceLoader로 사용되므로, 정확한 애플리케이션 context type에 따라 resource는 ClassPathResource, FileSystemResource 또는 ServletContextResource를 통해 로드됩니다.
특정 Resource type이 사용되도록 강제해야 하는 경우 prefix를 사용할 수 있습니다. 다음 두 예제는 ClassPathResource와 UrlResource(후자는 filesystem의 file에 접근하는 데 사용됨)를 강제하는 방법을 보여 줍니다:
1<property name="template" value="classpath:some/resource/path/myTemplate.txt"/>
1<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
MyBean class가 annotation-driven 설정에 사용되도록 리팩터링되는 경우, myTemplate.txt에 대한 path는 예를 들어 Spring Environment에 제공되는 프로퍼티 file에서 template.path라는 key 아래에 저장될 수 있습니다(Environment Abstraction을 참조하십시오).
그런 다음 @Value annotation을 사용하여 프로퍼티 placeholder를 통해 template path를 참조할 수 있습니다(Using @Value를 참조하십시오). Spring은 template path의 값을 string으로 가져오고, 특수 PropertyEditor가 string을 Resource 객체로 변환하여 MyBean 생성자에 주입합니다. 다음 예제는 이를 달성하는 방법을 보여 줍니다.
1@Component 2public class MyBean { 3 4 private final Resource template; 5 6 public MyBean(@Value("${template.path}") Resource template) { 7 this.template = template; 8 } 9 10 // ... 11}
1@Component 2class MyBean(@Value("${template.path}") private val template: Resource)
classpath의 여러 위치(예: classpath의 여러 jar)에 있는 동일한 path에서 발견되는 여러 template을 지원하려면, 특수 classpath*: prefix와 wildcarding을 사용하여 templates.path key를 classpath*:/config/templates/*.txt로 정의할 수 있습니다.
MyBean class를 다음과 같이 재정의하면, Spring은 template path pattern을 MyBean 생성자에 주입될 수 있는 Resource 객체의 array로 변환합니다.
1@Component 2public class MyBean { 3 4 private final Resource[] templates; 5 6 public MyBean(@Value("${templates.path}") Resource[] templates) { 7 this.templates = templates; 8 } 9 10 // ... 11}
1@Component 2class MyBean(@Value("${templates.path}") private val templates: Resource[])
이 섹션에서는 XML과 함께 작동하는 shortcut, wildcard 사용 방법 및 기타 세부 사항을 포함하여 resource로 애플리케이션 context를 생성하는 방법을 다룹니다.
애플리케이션 context 생성자(특정 애플리케이션 context type에 대한)는 일반적으로 context 정의를 구성하는 XML file과 같은 resource의 location path로 string 또는 string array를 받습니다.
이러한 location path에 prefix가 없는 경우, 해당 path에서 생성되어 bean definition을 로드하는 데 사용되는 특정 Resource type은 특정 애플리케이션 context에 따라 달라지며, 그에 적합합니다. 예를 들어, 다음 예제는 ClassPathXmlApplicationContext를 생성합니다:
1ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
1val ctx = ClassPathXmlApplicationContext("conf/appContext.xml")
bean definition은 ClassPathResource가 사용되기 때문에 classpath에서 로드됩니다. 그러나 다음 예제는 FileSystemXmlApplicationContext를 생성합니다:
1ApplicationContext ctx = 2 new FileSystemXmlApplicationContext("conf/appContext.xml");
1val ctx = FileSystemXmlApplicationContext("conf/appContext.xml")
이제 bean definition은 filesystem 위치(이 경우, 현재 working 디렉터리를 기준으로)에서 로드됩니다.
location path에서 특수 classpath prefix 또는 표준 URL prefix를 사용하는 것은 bean definition을 로드하기 위해 생성되는 기본 Resource type을 override한다는 점에 유의하십시오. 다음 예제를 고려해 보십시오:
1ApplicationContext ctx = 2 new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
1val ctx = FileSystemXmlApplicationContext("classpath:conf/appContext.xml")
FileSystemXmlApplicationContext를 사용하면 bean definition이 classpath에서 로드됩니다. 그러나 여전히 FileSystemXmlApplicationContext입니다. 이후에 ResourceLoader로 사용되는 경우, prefix가 없는 모든 path는 여전히 filesystem path로 처리됩니다.
ClassPathXmlApplicationContext Instances — ShortcutsClassPathXmlApplicationContext는 편리한 인스턴스화를 가능하게 하는 여러 생성자를 노출합니다. 기본 아이디어는, XML file 이름(선행 path 정보 없이)만 포함하는 string array와 Class를 제공할 수 있다는 것입니다. 그런 다음 ClassPathXmlApplicationContext는 제공된 class로부터 path 정보를 유도합니다.
다음 디렉터리 layout을 고려해 보십시오:
com/
example/
services.xml
repositories.xml
MessengerService.class
다음 예제는 classpath에 있는 services.xml 및 repositories.xml file에 정의된 bean으로 구성된 ClassPathXmlApplicationContext 인스턴스를 인스턴스화하는 방법을 보여 줍니다:
1ApplicationContext ctx = new ClassPathXmlApplicationContext( 2 new String[] {"services.xml", "repositories.xml"}, MessengerService.class);
1val ctx = ClassPathXmlApplicationContext(arrayOf("services.xml", "repositories.xml"), MessengerService::class.java)
다양한 생성자에 대한 자세한 내용은 ClassPathXmlApplicationContext javadoc을 참조하십시오.
애플리케이션 context 생성자 값의 resource path는 앞에서 본 것처럼 simple path일 수 있으며, 각각은 target Resource에 대한 one-to-one mapping을 가지거나, 또는 특수 classpath*: prefix나 internal Ant-style pattern(Spring의 PathMatcher 유틸리티를 사용하여 match)을 포함할 수도 있습니다. 후자의 두 가지는 사실상 wildcard입니다.
이 메커니즘의 한 가지 사용 예는 component-style 애플리케이션 assembly가 필요할 때입니다. 모든 component는 잘 알려진 location path에 context definition fragment를 _publish_할 수 있으며, 최종 애플리케이션 context가 동일한 path에 classpath*: prefix를 사용하여 생성될 때, 모든 component fragment가 자동으로 수집됩니다.
이러한 wildcarding은 애플리케이션 context 생성자에서 resource path를 사용할 때(또는 PathMatcher 유틸리티 클래스 계층을 직접 사용할 때)만 특정하며, construction 시점에 resolve된다는 점에 유의하십시오. 이는 Resource type 자체와는 관련이 없습니다. Resource는 한 번에 하나의 resource만 가리키므로, 실제 Resource를 구성하기 위해 classpath*: prefix를 사용할 수 없습니다.
Path location에는 다음 예제와 같이 Ant-style pattern이 포함될 수 있습니다:
/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml
path location에 Ant-style pattern이 포함된 경우, resolver는 wildcard를 resolve하기 위해 더 복잡한 절차를 따릅니다. 마지막 non-wildcard segment까지의 path에 대해 Resource를 생성하고, 그로부터 URL을 얻습니다.
이 URL이 jar: URL 또는 컨테이너-specific variant(예: WebLogic의 zip:, WebSphere의 wsjar 등)가 아닌 경우, 이 URL로부터 java.io.File을 얻고 filesystem을 탐색하여 wildcard를 resolve하는 데 사용합니다. jar URL의 경우, resolver는 이 URL로부터 java.net.JarURLConnection을 얻거나 jar URL을 수동으로 parsing한 다음, jar file의 내용을 탐색하여 wildcard를 resolve합니다.
지정된 path가 이미 file URL인 경우(기본 ResourceLoader가 filesystem 기반이기 때문에 암묵적으로, 또는 명시적으로), wildcarding은 완전히 portable한 방식으로 작동하는 것이 보장됩니다.
지정된 path가 classpath location인 경우, resolver는 Classloader.getResource() 호출을 수행하여 마지막 non-wildcard path segment URL을 얻어야 합니다. 이는 path의 node일 뿐(끝의 file이 아님)이므로, 이 경우 정확히 어떤 종류의 URL이 반환되는지는( ClassLoader javadoc에서) 실제로 정의되어 있지 않습니다.
실제로, 이는 항상 디렉터리를 나타내는 java.io.File(classpath resource가 filesystem 위치로 resolve되는 경우) 또는 jar URL( classpath resource가 jar 위치로 resolve되는 경우)입니다. 그럼에도 불구하고, 이 작업에는 portability 문제가 있습니다.
마지막 non-wildcard segment에 대해 jar URL이 얻어지는 경우, resolver는 jar 내용을 탐색하고 wildcard를 resolve할 수 있도록 이 URL로부터 java.net.JarURLConnection을 얻거나 jar URL을 수동으로 parsing할 수 있어야 합니다. 이는 대부분의 환경에서 작동하지만, 일부 환경에서는 실패하며, jar에서 오는 resource의 wildcard resolution에 의존하기 전에 특정 환경에서 이를 철저히 테스트할 것을 강력히 권장합니다.
classpath*: PrefixXML 기반 애플리케이션 context를 구성할 때, location string은 다음 예제와 같이 특수 classpath*: prefix를 사용할 수 있습니다:
1ApplicationContext ctx = 2 new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
1val ctx = ClassPathXmlApplicationContext("classpath*:conf/appContext.xml")
이 특수 prefix는 주어진 이름과 일치하는 모든 classpath resource를 얻어야 함을 지정합니다(내부적으로는 본질적으로 ClassLoader.getResources(…) 호출을 통해 발생) 그리고 그런 다음 이를 병합하여 최종 애플리케이션 context definition을 형성합니다.
wildcard classpath는 기반이 되는
ClassLoader의getResources()메서드에 의존합니다. 대부분의 애플리케이션 서버는 요즘 자체ClassLoader구현을 제공하므로, 특히 jar file을 다룰 때 그 동작이 달라질 수 있습니다.classpath*가 작동하는지 확인하는 간단한 테스트는 classpath에 있는 jar 내부의 file을 로드하기 위해ClassLoader를 사용하는 것입니다:getClass().getClassLoader().getResources("<someFileInsideTheJar>"). classpath의 서로 다른 jar에 있는 동일한 이름과 path를 가진 file과 함께 이 테스트를 시도해 보십시오. 부적절한 결과가 반환되는 경우,ClassLoader동작에 영향을 줄 수 있는 설정에 대해 애플리케이션 서버 문서를 확인하십시오.
또한 location path의 나머지 부분에서 PathMatcher pattern과 classpath*: prefix를 결합할 수 있습니다(예: classpath*:META-INF/*-beans.xml). 이 경우 resolution 전략은 상당히 단순합니다. 마지막 non-wildcard path segment에 대해 ClassLoader.getResources() 호출을 사용하여 class loader 계층에서 모든 일치하는 resource를 가져오고, 그런 다음 각 resource에서 앞에서 설명한 동일한 PathMatcher resolution 전략을 wildcard subpath에 대해 사용합니다.
classpath*:는 Ant-style pattern과 결합될 때, 실제 target file이 filesystem에 존재하지 않는 한 pattern이 시작되기 전에 적어도 하나의 root 디렉터리가 있어야만 안정적으로 작동한다는 점에 유의하십시오. 이는 classpath*:*.xml과 같은 pattern이 jar file의 root에서 file을 검색하지 못하고, 확장된 디렉터리의 root에서만 검색할 수 있음을 의미합니다.
Spring의 classpath entry 검색 기능은 빈 string(검색할 잠재적 root를 나타냄)에 대해 file system 위치만 반환하는 JDK의 ClassLoader.getResources() 메서드에 기원을 둡니다. Spring은 또한 URLClassLoader runtime 설정과 jar file의 java.class.path manifest를 평가하지만, 이것이 portable한 동작으로 이어지는 것은 보장되지 않습니다.
classpath package의 scanning에는 classpath에 해당 디렉터리 entry가 존재해야 합니다. Ant로 JAR를 빌드할 때, JAR task의
files-onlyswitch를 활성화하지 마십시오. 또한, 일부 환경(예: JDK 1.7.0_45 이상에서 stand-alone 애플리케이션(여기서는 manifest에 'Trusted-Library'를 설정해야 함. 자세한 내용은 stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources를 참조하십시오))에서는 보안 정책에 따라 classpath 디렉터리가 노출되지 않을 수 있습니다. module path(Java Module System)에서는 Spring의 classpath scanning이 일반적으로 예상대로 작동합니다. 이 경우에도 resource를 전용 디렉터리에 두는 것이 매우 권장되며, jar file root level 검색과 관련된 앞에서 언급한 portability 문제를 피할 수 있습니다.
classpath: resource에 대한 Ant-style pattern은 검색할 root 패키지가 여러 classpath 위치에서 사용 가능한 경우, 일치하는 resource를 찾는 것이 보장되지 않습니다. 다음 resource location 예제를 고려해 보십시오:
com/mycompany/package1/service-context.xml
이제 누군가가 해당 file을 찾기 위해 사용하려 할 수 있는 Ant-style path를 고려해 보십시오:
classpath:com/mycompany/**/service-context.xml
이러한 resource는 classpath의 한 위치에만 존재할 수 있지만, 위와 같은 path를 사용하여 이를 resolve하려고 하면, resolver는 getResource("com/mycompany");에 의해 반환된 (첫 번째) URL을 기반으로 작동합니다. 이 base 패키지 node가 여러 ClassLoader 위치에 존재하는 경우, 원하는 resource는 첫 번째로 발견된 위치에 존재하지 않을 수 있습니다.
따라서 이러한 경우, com.mycompany base 패키지를 포함하는 모든 classpath 위치를 검색하는 동일한 Ant-style pattern과 함께 classpath*: 사용을 선호해야 합니다: classpath*:com/mycompany/**/service-context.xml.
FileSystemResource CaveatsFileSystemApplicationContext에 연결되지 않은 FileSystemResource(FileSystemApplicationContext가 실제 ResourceLoader가 아닌 경우)는 absolute path와 relative path를 예상대로 처리합니다. relative path는 현재 working 디렉터리를 기준으로 하고, absolute path는 filesystem root를 기준으로 합니다.
그러나 backwards compatibility(역사적인) 이유로, FileSystemApplicationContext가 ResourceLoader인 경우에는 이것이 변경됩니다. FileSystemApplicationContext는 연결된 모든 FileSystemResource 인스턴스가 선행 slash로 시작하든 그렇지 않든 모든 location path를 relative로 처리하도록 강제합니다. 실제로는 다음 예제들이 동일하다는 것을 의미합니다:
1ApplicationContext ctx = 2 new FileSystemXmlApplicationContext("conf/context.xml");
1val ctx = FileSystemXmlApplicationContext("conf/context.xml")
1ApplicationContext ctx = 2 new FileSystemXmlApplicationContext("/conf/context.xml");
1val ctx = FileSystemXmlApplicationContext("/conf/context.xml")
다음 예제들도 동일합니다(한 경우는 relative이고 다른 경우는 absolute이므로 서로 다르게 동작하는 것이 타당해 보이더라도):
1FileSystemXmlApplicationContext ctx = ...; 2ctx.getResource("some/resource/path/myTemplate.txt");
1val ctx: FileSystemXmlApplicationContext = ... 2ctx.getResource("some/resource/path/myTemplate.txt")
1FileSystemXmlApplicationContext ctx = ...; 2ctx.getResource("/some/resource/path/myTemplate.txt");
1val ctx: FileSystemXmlApplicationContext = ... 2ctx.getResource("/some/resource/path/myTemplate.txt")
실제로, 진정한 absolute filesystem path가 필요하다면, absolute path를 FileSystemResource 또는 FileSystemXmlApplicationContext와 함께 사용하는 것을 피하고, file: URL prefix를 사용하여 UrlResource 사용을 강제해야 합니다. 다음 예제는 이를 수행하는 방법을 보여 줍니다:
1// actual context type doesn't matter, the Resource will always be UrlResource 2ctx.getResource("file:///some/resource/path/myTemplate.txt");
1// actual context type doesn't matter, the Resource will always be UrlResource 2ctx.getResource("file:///some/resource/path/myTemplate.txt")
1// force this FileSystemXmlApplicationContext to load its definition via a UrlResource 2ApplicationContext ctx = 3 new FileSystemXmlApplicationContext("file:///conf/context.xml");
1// force this FileSystemXmlApplicationContext to load its definition via a UrlResource 2val ctx = FileSystemXmlApplicationContext("file:///conf/context.xml")
The BeanFactory API
Validation, Data Binding, and Type Conversion