-
[10] 추상화 - Resource 추상화Spring/Spring 핵심 기술 2020. 4. 21. 09:51반응형
SpringFramework에서는 java.net.URL interface를 org.springframework.core.io.Resource interface type으로 상속 받아 추상화합니다. java.net.URL에는 resource 접근과 관리에 대한 기능이 부족하여 org.springframework.core.io.Resource로의 추상화를 통해 필요한 기능들을 지원하고 있습니다. 다음은 부족한 기능들의 예입니다.
- class path 기준으로 resource를 읽어오는 기능이 필요하지만 java.net.URL에서는 필요로 하는 기능을 제공하지 않습니다.
- java.net.URL에는 ServletContext를 기준으로 상대 경로를 읽어오는 기능이 없습니다.
- 새로운 핸들러를 등록하여 특별한 URL 접두사를 만들어 사용은 가능하나 그 구현이 복잡하고 이를 편리하게 처리할 수 있는 method가 부족합니다.
(java.net.URL class는 World Wide Web상의 Resource를 가르키는 Uniform Resource Locator를 표현합니다.)
우리는 ApplicationContext를 생성할 때부터 이미 resource를 사용했습니다. XML file로 ApplicationContext를 생성할 때 class path와 file system 두 가지 기준으로 resource에 접근할 수 있습니다.
ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("context.xml");
ClassPathXmlApplicationContext()과 FileSystemXmlApplicationContext()에 매개 값으로 전달된 xml file을 가리키는 문자열은 resource를 가르킵니다. 즉, content.xml이라는 resource를 찾아서 bean 설정 file로 사용하게 됩니다. 위의 두 가지 ApplicationContext 생성 구문은 "context.xml"이라는 resource를 각각 classpath resource와 filesystem resource로써 resolving 하게 됩니다.
[Resource의 주요 method]
- getInputStream()
- exist() : Resource는 존재할 수도 있고 아닐 수도 있다고 가정하기 때문에 Resource의 존재여부를 확인하는 메서드를 제공합니다.
- isOpen()
- getDescription()
- getFile() : Resource를 file로 가져옵니다. 다만 모든 Resource를 항상 file로 가져올 수 있는 것은 아닙니다.
[Resource의 구현체]
- UrlResource : java.net.URL참고. "http", "https", "ftp", "file", "jar" 등의 접두어를 지원합니다.
- ClassPathResource : "classpath"라는 접두어를 붙여 표현한 resource이며 접두어에 붙은 resource는 class path resource가 됩니다.
- FileSystemResource
- ServletContextResource : 웹 어플리케이션 루트로 부터 상대경로를 사용하여 resource를 찾습니다.(읽어들이는 type이 Application Context와 관련이 있기 때문에 가장 많이 사용되는 resource입니다..)
[Resource 읽어오기]
1. 생성되는 ApplicationContext의 종류에 따라 이후 사용되는 resource type이 결정됩니다.
- ClassPathXmlApplicationContext -> Context root 이하의 모든 resource를 ClassPathResource로 간주합니다.
- FileSystemXmlApplicationContext -> Context root 이하의 모든 resource를 FileSystemResource로 간주합니다.
- WebApplicationContext -> Context root 이하의 모든 resource를 ServletContextResource로 간주합니다.
2. ApplicationContext 종류에 상관 상관없이 resource를 원하는 resource type으로 지정하고자 한다면 resource path를 매개변수로 전달할 때 java.net.URL에 정의된 "classpath:"와 같은 접두어를 붙인 location 문자열을 사용하면 됩니다. 일반적으로 WebApplitcationContext를 사용하므로 접두어 없이 ClassPathResource를 사용하고자 하면 ServletContextResource로 간주되어 되어 원하지 않는 결과를 보여줄 수 있으니 ClassPathResource를 사용하는 경우는 반드시 "classpath:"접두어를 붙여야 합니다.
- classpath:test.txt -> ClassPathResource
- file:///test/path/test.txt -> FileSystemResource
WebServerApplicationContext로 ApplicationContext를 생성하고 동일한 resource에 대해 classpath 접두어를 붙였을 때와 붙이지 않았을 때의 resource type(resource object의 class)을 확인해보도록 합시다. AppRunner.java를 다음과 같이 수정 후 실행해주세요.
@Component public class AppRunner implements ApplicationRunner { @Autowired ApplicationContext resourceLoader; // ① @Override public void run(ApplicationArguments args) throws Exception { System.out.println(resourceLoader.getClass()); Resource resource1 = resourceLoader.getResource("classpath:test.txt"); // ② System.out.println(resource1.getClass()); Resource resource2 = resourceLoader.getResource("test.txt"); // ③ System.out.println(resource2.getClass()); } }
① WebApplicationContext를 주입받습니다. Context root부터 모든 resource는 ServletContextResource로 간주됩니다.
② resource를 가져올 때 접두어 "classpath:"를 붙여서 ClassPathResource임을 명시하여 가져옵니다.
③ 접두어 없이 resource를 가져옵니다.
실행결과를 보면 현재 Context는 AnnotationConfigServletWebServerApplicationContext 즉 WebApplicationContext임을 알 수 있습니다. 그러므로 Context root 이하의 모든 resource는 ServletContextResource가 됩니다.
하지만 resouce에 "classpaath:" prefix를 붙인 경우는 ClassPathResource로 resource를 가져오는 것을 확인할 수 있습니다.
'Spring > Spring 핵심 기술' 카테고리의 다른 글
[12] 추상화 - Data Binding 추상화 : PropertyEditor (0) 2020.04.23 [11] 추상화 - Validation 추상화 (0) 2020.04.22 [09] ApplicationContext - ResourceLoader (0) 2020.04.21 [08] ApplicationContext - ApplicationEventPublisher (0) 2020.04.19 [07] ApplicationContext - MessageSource (0) 2020.04.17