1. 개요

이 짧은 사용방법(예제)에서는 Class.getResource()ClassLoader.getResource() 메서드 간의 차이점을 살펴보겠습니다 .

2. getResource()  메서드

Class 또는 ClassLoader 인스턴스에서 getResource() 메서드를 사용 하여 주어진 이름을 가진 리소스를 찾을 수 있습니다. 리소스는 데이터(예: 이미지, 텍스트, 오디오 등)로 간주됩니다. 경로 구분 기호로 항상 슬래시("/")를 사용해야 합니다.

이 메서드는 리소스를 읽기 위한 URL 개체를 반환하거나, 리소스를 찾을 수 없거나 호출자에게 리소스를 검색할 권한이 없는 경우 null 값을 반환합니다.

3. Class.getResource()

이제 클래스 인스턴스 를 사용하여 리소스를 얻는 방법을 살펴보겠습니다 . 클래스 개체 로 리소스를 찾을 때 절대 또는 상대 경로를 전달할 수 있습니다 .

주어진 클래스와 연관된 리소스 검색 규칙은 클래스의 클래스 로더에 의해 구현됩니다.

리소스를 찾는 프로세스는 클래스 개체의 클래스 로더에 Delegation됩니다. 즉, Class 인스턴스 에 정의된 getResouce() 메서드 는 결국 ClassLoadergetResouce() 메서드를 호출합니다.

Delegation 전에 절대 리소스 이름은 지정된 리소스 이름에서 파생됩니다. 절대 리소스 이름을 만들 때 다음 알고리즘이 사용됩니다.

  • 리소스 이름이 선행 슬래시("/")로 시작하면 리소스 이름이 절대적임을 나타냅니다. 절대 리소스 이름은 선행 슬래시가 제거되고 수정 없이 리소스를 찾기 위한 적절한 ClassLoader 메서드로 전달됩니다.
  • 제공된 리소스 이름이 슬래시로 시작하지 않으면 이름은 클래스의 패키지에 상대적인 것으로 처리됩니다. 상대 이름은 먼저 절대 이름으로 변환된 다음 ClassLoader 메서드로 전달됩니다.

먼저 com/bealdung/resource 디렉토리 내에 정의된 example.txt 리소스 가 있다고 가정해 보겠습니다 . 또한 com.baeldung.resourcee 패키지 내에 정의된 ClassGetResourceExample 클래스가 있다고 가정해 보겠습니다 .

이제 절대 경로를 사용하여 리소스를 검색할 수 있습니다.

void givenAbsoluteResourcePath_whenGetResource_thenReturnResource() {
    URL resourceAbsolutePath = ClassGetResourceExample.class
        .getResource("/com/baeldung/resource/example.txt");
    Assertions.assertNotNull(resourceAbsolutePath);
}

Class.getResource() 를 사용할 때 절대 리소스 경로는 선행 슬래시로 시작해야 합니다.

또한 리소스가 클래스와 동일한 패키지 내에 있으므로 상대 경로를 사용하여 검색할 수도 있습니다.

void givenRelativeResourcePath_whenGetResource_thenReturnResource() {
    URL resourceRelativePath = ClassGetResourceExample.class.getResource("example.txt");
    Assertions.assertNotNull(resourceRelativePath);
}

그러나 리소스가 클래스와 동일한 패키지 내에서 정의된 경우에만 상대 경로를 사용하여 리소스를 가져올 수 있다는 점을 언급하는 것이 중요합니다. 그렇지 않으면 값으로 null 을 얻게 됩니다.

4. ClassLoader.getResource()

이름에서 알 수 있듯이 ClassLoader 는 클래스 로드를 담당하는 클래스를 나타냅니다. 모든 Class 인스턴스에는 해당 ClassLoader 에 대한 참조가 포함 됩니다.

ClassLoader 클래스 는 Delegation 모델을 사용하여 클래스와 리소스를 검색합니다. 또한 ClassLoader 클래스의 각 인스턴스에는 연관된 부모 ClassLoader 가 있습니다.

리소스를 찾으라는 요청을 받으면 ClassLoader 인스턴스는  리소스 자체를 찾으려고 시도하기 전에 먼저 검색을 부모 ClassLoader 에 Delegation합니다 .

부모 ClassLoader 가 존재하지 않는 경우 부트스트랩 클래스 로더라고 하는 가상 머신의 내장 ClassLoader 경로가 검색됩니다. 부트스트랩 클래스 로더에는 부모가 없지만 ClassLoader 인스턴스의 부모 역할을 할 수 있습니다.

또는 이 메서드는 이전 검색이 실패한 경우 리소스를 찾기 위해 findResource() 메서드를 호출합니다 .

입력으로 지정된 리소스 이름은 항상 절대적인 것으로 간주됩니다. Java가 클래스 경로에서 리소스를 로드한다는 점에 유의하는 것이 중요합니다.

절대 경로와 ClassLoader 인스턴스 를 사용하여 리소스를 가져옵니다 .

void givenAbsoluteResourcePath_whenGetResource_thenReturnResource() {
    URL resourceAbsolutePath = ClassLoaderGetResourceExample.class.getClassLoader()
        .getResource("com/baeldung/resource/example.txt");
    Assertions.assertNotNull(resourceAbsolutePath);
}

ClassLoader.getResource() 를 호출할 때 절대 경로를 정의할 때 선행 슬래시를 생략해야 합니다.

ClassLoader 인스턴스를 사용 하면 상대 경로를 사용하여 리소스를 가져올 수 없습니다 .

void givenRelativeResourcePath_whenGetResource_thenReturnNull() {
    URL resourceRelativePath = ClassLoaderGetResourceExample.class.getClassLoader()
        .getResource("example.txt");
    Assertions.assertNull(resourceRelativePath);
}

위의 테스트는 메서드가 결과로 null 값을 반환함을 보여줍니다.

5. 결론

이 짧은 사용방법(예제)에서는 ClassClassLoader 인스턴스 에서 getResource() 메서드를 호출하는 것의 차이점에 대해 설명했습니다 . 요약하면 Class 인스턴스 를 사용하여 메서드를 호출할 때 상대 또는 절대 리소스 경로를 전달할 수 있지만 ClassLoader 에서 메서드를 호출할 때는 절대 경로만 사용할 수 있습니다 .

항상 그렇듯이 코드는 GitHub에서 사용할 수 있습니다 .

Generic footer banner