1. 개요
이 예제에서는 문자열로 텍스트를 포함하는 리소스의 내용을 Spring 빈에 주입하는 다양한 방법을 살펴볼 것 입니다.
리소스를 찾고 콘텐츠를 읽는 방법을 살펴보겠습니다.
또한 여러 빈에서 로드된 리소스를 공유하는 방법을 보여줍니다. XML 기반 주입 을 사용 하고 XML 속성 파일에서 빈을 선언 하여 동일한 결과를 얻을 수도 있지만 의존성 주입과 관련된 어노테이션을 사용하여 이를 보여줍니다 .
2. 리소스 사용
Resource 인터페이스 를 사용하여 리소스 파일 찾기를 단순화할 수 있습니다 . Spring은 제공된 경로에 따라 선택할 리소스 구현을 결정하는 리소스 로더를 사용하여 리소스를 찾고 읽을 수 있도록 도와줍니다 . 리소스 는 콘텐츠 자체가 아니라 리소스의 콘텐츠에 효과적으로 액세스하는 방법입니다 .
classpath의 리소스에 대한 Resource 인스턴스 를 획득하는 몇 가지 방법을 살펴보겠습니다 .
2.1. 리소스 로더 사용
지연 로딩을 선호한다면 ResourceLoader 클래스를 사용할 수 있습니다 .
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource("classpath:resource.txt");
@Autowired 를 사용하여 ResourceLoader 를 빈에 주입할 수도 있습니다 .
@Autowired
private ResourceLoader resourceLoader;
2.2. @Value 사용
@Value 를 사용하여 리소스 를 Spring 빈에 직접 주입할 수 있습니다 .
@Value("classpath:resource.txt")
private Resource resource;
3. 리소스 에서 문자열 로 변환
Resource 에 접근할 수 있게 되면 그것을 String 으로 읽을 수 있어야 합니다 . 이 작업을 수행하기 위해 정적 메서드 asString 을 사용하여 ResourceReader 유틸리티 클래스를 만들어 보겠습니다 .
먼저 InputStream 을 획득해야 합니다 .
InputStream inputStream = resource.getInputStream();
다음 단계는 이 InputStream 을 가져와 String 으로 변환하는 것 입니다. Spring 고유의 FileCopyUtils#copyToString 메소드를 사용할 수 있습니다.
public class ResourceReader {
public static String asString(Resource resource) {
try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) {
return FileCopyUtils.copyToString(reader);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
// more utility methods
}
예를 들어 Spring의 StreamUtils 클래스 의 copyToString 을 사용하여 이를 달성하는 다른 많은 방법이 있습니다 .
또한 경로에 대한 Resource 를 검색하는 또 다른 유틸리티 메서드 인 readFileToString 을 만들고 asString 메서드를 호출하여 이를 String 으로 변환해 보겠습니다 .
public static String readFileToString(String path) {
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource(path);
return asString(resource);
}
4. 구성 클래스 추가
각 빈이 리소스 String 을 개별적으로 주입해야 하는 경우, String 의 개별 복사본을 가진 빈이 코드를 복제하고 메모리를 더 많이 사용할 가능성이 있습니다 .
애플리케이션 컨텍스트를 로드할 때 리소스의 내용을 하나 이상의 Spring 빈에 주입하여 보다 깔끔한 솔루션을 얻을 수 있습니다. 이러한 방식으로 이 콘텐츠를 사용해야 하는 다양한 빈에서 리소스를 읽기 위한 구현 세부 정보를 숨길 수 있습니다.
@Configuration
public class LoadResourceConfig {
// Bean Declarations
}
4.1. 리소스 문자열을 보유하는 Bean 사용
@Configuration 클래스 에 리소스 내용을 담기 위해 빈을 선언합시다 :
@Bean
public String resourceString() {
return ResourceReader.readFileToString("resource.txt");
}
이제 @Autowired 어노테이션 을 추가하여 등록된 빈을 필드에 주입해 보겠습니다 .
public class LoadResourceAsStringIntegrationTest {
private static final String EXPECTED_RESOURCE_VALUE = "..."; // The string value of the file content
@Autowired
@Qualifier("resourceString")
private String resourceString;
@Test
public void givenUsingResourceStringBean_whenConvertingAResourceToAString_thenCorrect() {
assertEquals(EXPECTED_RESOURCE_VALUE, resourceString);
}
}
이 경우에는 @Qualifier 어노테이션과 빈의 이름을 사용합니다. 같은 유형의 여러 필드를 삽입해야 할 수도 있기 때문입니다 – String .
한정자에 사용된 Bean 이름은 구성 클래스에서 Bean을 생성하는 메소드의 이름에서 파생된다는 점에 유의해야 합니다.
5. SpEL 사용
마지막으로 리소스 파일을 클래스의 필드에 직접 로드하는 데 필요한 코드를 설명하기 위해 Spring Expression Language를 사용하는 방법을 살펴보겠습니다.
@Value 어노테이션을 사용하여 파일 내용을 resourceStringUsingSpel 필드에 삽입해 보겠습니다 .
public class LoadResourceAsStringIntegrationTest {
private static final String EXPECTED_RESOURCE_VALUE = "..."; // The string value of the file content
@Value(
"#{T(com.baeldung.loadresourceasstring.ResourceReader).readFileToString('classpath:resource.txt')}"
)
private String resourceStringUsingSpel;
@Test
public void givenUsingSpel_whenConvertingAResourceToAString_thenCorrect() {
assertEquals(EXPECTED_RESOURCE_VALUE, resourceStringUsingSpel);
}
}
여기 에서 "classpath:" 를 사용하여 파일의 위치를 설명하는 ResourceReader#readFileToString 을 호출했습니다. @Value 어노테이션 내부에 접두사가 붙은 경로 입니다.
SpEL의 코드 양을 줄이기 위해 Apache Commons FileUtils 를 사용하여 제공된 경로에서 파일에 액세스하는 ResourceReader 클래스의 도우미 메서드를 만들었습니다.
public class ResourceReader {
public static String readFileToString(String path) throws IOException {
return FileUtils.readFileToString(ResourceUtils.getFile(path), StandardCharsets.UTF_8);
}
}
6. 결론
이 사용방법(예제)에서는 리소스를 String 으로 변환하는 몇 가지 방법을 검토했습니다 .
먼저 파일에 접근하기 위한 Resource 를 생성하는 방법과 Resource 에서 String 으로 읽는 방법을 알아보았습니다 .
다음으로 리소스 로딩 구현을 숨기고 문자열이 자동 연결되도록 하는 @Configuration 에 정규화된 빈을 생성하여 빈 간에 문자열 내용을 공유하는 방법도 보여주었습니다 .
마지막으로 우리는 컴팩트하고 즉각적인 솔루션을 제공하는 SpEL을 사용했지만 너무 복잡해지지 않도록 사용자 지정 도우미 기능이 필요했습니다.
항상 그렇듯이 예제 코드는 GitHub 에서 찾을 수 있습니다.