Goal
- 스프링의 추상화 중 하나인 Resource 추상화에 대해 알아본다
- 추상화를 한 이유에 대해 알아본다
- Resource 인터페이스의 동작과정과 구현체를 알아본다
- Resource를 읽어오는 방법에 대해 알아본다
Resource 추상화란 ?
- 구체적으로 java.net.URL를 추상화 한 것
- org.springframework.core.io.Resource 클래스로 감싸서 로우 레벨에 접근하는 기능을 추상화하였다.
가져오는 기능은 아래 포스팅 참고
https://dev-rosiepoise.tistory.com/99
스프링이 Resource를 왜 추상화 하였는가?
- classpath 기준으로 리소스 읽어오는 기능의 부재
- 기존의 java.net.URL은 기본적으로 지원하는 프로토콜이 http, https, ftp, file, jar
- ServletContext를 기준으로 상대 경로를 읽어오는 기능 부재
- 새로운 핸들러를 등록하여 특별한 URL 접미사를 만들어 사용할 수 있지만 복잡하고 편의성 메소드 부족
Resource 인터페이스
public interface Resource extends InputStreamSource
- InputStreamSource를 구현
- getInputStream()
- 주요 메소드 // java 8이상 인터페이스의 default메소드
- default boolean isReadable() {return this.exists();} // 항상 존재한다고 가정하지 않기 때문에 확인
- default boolean isOpen() {return false;}
- default boolean isFile() {return false;}
- String getDescription();
- 전체 경로 포함한 파일 이름 또는 실제 URL
- File getFile() throws IOException;
- 항상 모든 리소스를 파일로 가져올 수 있는 것은 아님
동작과정
var ctx = new ClassPathXmlApplicationContext("test.xml");
classpath 기준으로 내부적으로 location("test.xml"라는 문자열)에 해당하는 리소스를 찾아서 빈 설정파일로 사용
var ctx = new FileSystemXmlApplicationContext("test.xml");
file system 경로 기준으로 내부적으로 location("test.xml"라는 문자열)에 해당하는 리소스를 찾아서 빈 설정파일로 사용
구현체
- UrlResource
- ClassPathResource
- classpath 접두어 사용
- FileSystemResource
- ServletContextResource
- 웹 어플리케이션 루트에서 상대 경로로 리소스 찾는다
- 읽어들이는 리소스 타입이 applicationContext와 관련이 있기 때문에 가장 많이 쓰인다
Resource 읽어오기
Resource의 타입은 location 문자열과 ApplicationContext 타입에 따라 결정 된다
- ClassPathXmlApplicationContext -> ClassPathResource
- FileSystemXmlApplicationContext -> FileSystemResource
- WebApplicationContext -> ServletContextResource
- WebApplicationContext 이하로는 ServletContextResource를 사용한다
ApplicationContext의 타입에 상관없이 리소르 타입을 강제하려면 java.net.URL 접두어(+classpath:)중 하나를 사용 가능
접두어를 사용하면 보다 명시적이기 때문에, 이 방법을 추천한다.
- classpath:com/demo/config.xml -> ClassPathResource
- file:///some/resource/path/config.xml -> FileSystemResource
검증하기
classpath 접두어를 사용한 경우
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ResourceLoader resourceLoader;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(resourceLoader.getClass());
Resource resource = resourceLoader.getResource("classpath:/text.txt");
System.out.println(resource.getClass());
System.out.println(resource.exists());
System.out.println(resource.getDescription());
System.out.println(Files.readString(Path.of(resource.getURI())));
}
}
결과
class org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
class org.springframework.core.io.ClassPathResource
true
class path resource [text.txt]
hello spring
classpath 접두어를 사용하지 않은 경우
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ResourceLoader resourceLoader;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(resourceLoader.getClass());
Resource resource = resourceLoader.getResource("text.txt");
System.out.println(resource.getClass());
System.out.println(resource.exists());
System.out.println(resource.getDescription());
System.out.println(Files.readString(Path.of(resource.getURI())));
}
}
결과
class org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
class org.springframework.web.context.support.ServletContextResource
false
ServletContext resource [/text.txt]
2023-07-25T12:34:11.325+09:00 INFO 43812 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger :
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-07-25T12:34:11.345+09:00 ERROR 43812 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Failed to execute ApplicationRunner
=> 해당하는 리소스를 찾지 못했고, 없는 파일을 읽으려고 시도하였기 때문에 에러 발생
참고
스프링입문 강의 by 백기선
https://www.inflearn.com/course/lecture?courseSlug=spring&unitId=15538 https://www.inflearn.com/course/spring_revised_edition/dashboard
https://www.inflearn.com/course/spring_revised_edition/dashboard
'Spring > about spring' 카테고리의 다른 글
[데이터 바인딩 추상화] PropertyEditor (0) | 2023.07.28 |
---|---|
[Resource / Validation] Validation 추상화 (0) | 2023.07.26 |
[IoC 컨테이너와 빈] ResourceLoader (0) | 2023.07.24 |
[IoC 컨테이너와 빈] ApplicationEvent Publisher (0) | 2023.07.24 |
[IoC 컨테이너와 빈] MessageSource (0) | 2023.07.24 |