10.Resource 추상화

지금까지 ApplicationContext는 단순한 빈 팩토리가아니라 여러가지 기능을 하는것을 알아봤었다.

Resource 추상화

지금까지는 IoC에 대해 살펴봤다면 지금부터는 추상화에 대해 알아보겠다

스프링에서는 Reosurce(org.springframework.core.io.Resource)를 추상화 하였다.

java.net.URL를 Resource라는 클래스로 감싸서 추상화함. 스프링입장에서 필요한 클래스패스에서 리소스를 가져올 수 있게함.

추상화 이유

java.net.URL이 클래스패스를 기준으로 리소스를 가져오는 기능이 없었음.
또한 java.net.URL이 여러가지 프리픽스(ftp,http 등)을 제공하는데 스프링입장에선 클래스패스를 기반으로 가져오는것도 필요했다.(위와 동일한내용)
(기존스프링은 ClassPathXmlApplicationContext으로 리소스를 가져와야했음.)
클래스 패스를 기반으로 가져올 수 있도록 할 수는 있지만(새로운 핸들러 등록하여) 구현이 복잡하고 편의성 메소드가 부족하다.

1
2
3
4
5
6
...
var ctx = new ClassPathXmlApplicationContext("sangheon.xml");

// 내부적으로 getResource를 호출(그러나 다른 구현체임)
// FileSystemXmlApplicationContex 도 마찬가지

여러 메소드는 내부적으로 resource관련 메소드를 호출한다. 즉 우리는 모르게 리소스의 구현체를 사용하고 있었다.

Resource 인터페이스

https://www.google.com/url?q=https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/Resource.html&ust=1579648260000000&usg=AFQjCNFJPcfSP77r_I5NqPaHMR1tElL6kg&hl=ko 참고
getInputStream()
exitst()
isOpen()
getDescription(): 전체 경로 포함한 파일 이름 또는 실제 URL

Resource 인터페이스의 구현체

  • UrlResource: java.net.URL 참고, 기본으로 지원하는 프로토콜 http, https, ftp, file, jar.
  • ClassPathResource: 지원하는 접두어 classpath:
  • FileSystemResource
  • ServletContextResource: 웹 애플리케이션 루트에서 상대 경로로 리소스 찾는다.
    (얘를 가장 많이 쓰는데 읽어들이는 리소스 타입이 ApplicationContext와 관련있기 때문.)

ApplicationContext

Resource의 타입은 locaion 문자열과 ApplicationContext의 타입에 따라 결정 된다.
ApplicationContext가 FileSystemXmlApplicationContext 이면 매개변수로 받는 문자열은 filesystem resource로 리졸빙을 한다.
WebApplicationContext 이면 문자열은 서블릿 컨텍스트 리소스로 리졸빙을 한다.

그래서 문자열은 내가 사용할 ApplicationContext에 따라 달라진다.

하지만 ApplicationContext의 타입에 상관없이 리소스 타입을 강제하려면 java.net.URL 접두어(+ classpath:)중 하나를 사용할 수 있다..
예시

  • classpath:me/whiteship/config.xml -> ClassPathResource
  • file:///some/resource/path/config.xml

강사님은 ApplicationContext를 쓰고 접두어를 사용할 것을 추천하였다.

1
2
3
4
5
6
7
8
@Autowired
ApplicationContext resourceLoader ;
...

print(resourceLoader.getClass()); // 서블릿웹서버어플리케이션 콘텍스트로 찍힌다,
Resouce resource = resourceLoader.getResource("classpath:text.txt");
print(resource.getClass()) // ClassPathResource로 찍힌다.
print(resource.exists()); //true

prefix를 지워보자

1
2
3
4
resource = resourceLoader.getResource("text.txt");
print(resource.getClass()) // 서블릿콘텍스트 리소스가 된다.
print(resource.exists()); //false

서블릿콘텍스트 리소스는 text.txt를 웹어플리케이션 루트 즉 컨텍스트 패스부터 찾게 나서게된다,
그런데 스프링부트가 띄워주는 내장형 톰켓에는 컨텍스트 패스가 지정되어있지 않으므로 리소스를 찾을 수 없다

Share