programing

Java 9에서 클래스 및 리소스 로드

muds 2023. 3. 2. 22:42
반응형

Java 9에서 클래스 및 리소스 로드

는 Reinhold의 인용문인 InfoQ에 관한기사를 읽고 있었습니다.

개발자는 Java 9의 Java 클래스 경로를 사용하여 Java 런타임에 클래스와 리소스 파일을 검색할 수 있습니다.다만 Java 9의 모듈에서는 개발자가 클래스 경로를 더 이상 필요로 하지 않습니다.

이제 위의 작업을 수행하는 적절한 Java 9 방법은 무엇입니까?예를 들어 이미지를 동적으로 로드하려면 어떻게 해야 합니까(상대 경로를 조작하지 않음).

더 흥미로운 것은 클래스가 이용 가능한지 확인하고 동적으로 결정하는 방법(예: Jackson이 이용 가능한지 확인하고, 이용 가능한 경우 JSON 시리얼라이제이션에 사용하고, 다른 것을 사용하지 않는 경우)입니다.

이 기사에서는 Spring Boot이 Java 9를 이미 지원하며 Spring Boot은 확실히 많은 동적 로드를 수행합니다.그럼 내가 볼 수 있는 스프링의 암호는 누가 알까?

첫째, 나는 위에서 인용한 내용을 말하거나 쓰지 않았다.난 절대 그렇게 말하지 않았을 거야.그것은 관련된 출판물의 허술한 보도일 뿐이다.

Java 9에서의 클래스 로딩 및 리소스 룩업에 대해 가장 중요한 것은 기본적으로 변경되지 않았다는 것입니다.호출하여 항상 가지고 있는 것과 동일한 방법으로 클래스 및 리소스를 검색할 수 있습니다.Class::forName및 다양한getResource*의 메서드Class그리고.ClassLoader클래스 경로 또는 모듈 경로에서 코드가 로드되었는지 여부에 관계없이 클래스.JDK 1.2와 마찬가지로 아직 3개의 내장 클래스 로더가 존재하며 동일한 위임 관계를 유지합니다.따라서 많은 기존 코드가 즉시 사용할 수 있습니다.

JEP 261에서 설명한 바와 같이 몇 가지 미묘한 점이 있습니다.내장 클래스 로더의 구체적인 유형이 변경되어 이전에 부트스트랩클래스 로더에 의해 로드되었던 일부 클래스가 보안을 강화하기 위해 플랫폼클래스 로더에 의해 로드되었습니다.빌트인 클래스 로더가 다음 코드인 것으로 가정하는 기존 코드URLClassLoader또는 부트스트랩클래스 로더에 의해 클래스가 로드되는 경우 약간의 조정이 필요할 수 있습니다.

마지막으로 중요한 차이점은 모듈 내의 비클래스 파일리소스는 디폴트로 캡슐화되어 있기 때문에 유효한 패키지가 이 아니면 모듈 외부에서 찾을없다는 것입니다.자체 모듈에서 리소스를 로드하려면 에서 리소스 검색 방법을 사용하는 것이 가장 좋습니다.Class ★★★★★★★★★★★★★★★★★」Module내의 수 ClassLoader를 찾을 수 은, 「」의 「」open모듈 패키지

[편집: 이 답변은 Mark의 권위 있는 답변보다 먼저 작성되었습니다.GitHub에서 이용할 수 있는 간단한 예를 제시하도록 수정했습니다.]

동영상에 따르면 Java 9에서의 클래스 로딩은 변경되지 않습니다.

예를 들어 다음과 같이 합시다.

  • 한 사람example.jar되어 있습니다.net.codetojoy.example.resources
  • net.codetojoy.example.Composer publicexport))
  • App를 사용하는 example.jar합니다.

App:

static InputStream getResourceAsStream(String resource) 
    throws Exception {

    // Load net/codetojoy/example/resource/image.jpg
    // Assume net.codetojoy.example.Composer is public/exported
    // resource is 'resource/image.jpg'

    InputStream result = Composer.class.getResourceAsStream(resource);

    return result;
}   

몇 .example.jarJDK 9:

구식 비모듈러형 항아리

ifexample.jar모듈이 아니라 코드가 작동합니다.클래스 로딩은 변경되지 않습니다.

오픈 패키지 포함 모듈러형 자

은 「」, 「」입니다.module-info.java 삭제:

module net.codetojoy.example {
    // export the Composer class
    exports net.codetojoy.example;

    // image is available
    opens net.codetojoy.example.resources;
}

이 경우 패키지가 열려 있기 때문에 클라이언트는 이미지를 로드할 수 있습니다.

오픈 패키지 미포함 모듈러형 jar

「」는,module-info.java 말합니다

module net.codetojoy.example {
    // export the Composer class
    exports net.codetojoy.example;

    // package not opened: image not available
    // opens net.codetojoy.example.resources;
}

이 경우 강력한 캡슐화로 인해 이미지를 로드할 수 없습니다.모듈은 패키지를 열지 않고 이미지를 보호합니다.

여기 GitHub에 모든 소스가 있습니다.

기존 답변 외에 다른 리소스 디렉터리 이름에 대한 비클래스 파일 리소스에 대한 캡슐화 규칙의 예를 제시하겠습니다.

getResourceAsStream 사양에는 패키지 이름이 이름에서 파생된 경우 리소스가 캡슐화된다고 나와 있습니다.

따라서 리소스의 디렉토리 이름이 유효한 Java 식별자가 아닌 경우 캡슐화되지 않습니다.즉, 모듈이 예를 들어 디렉토리 아래에 있는 리소스가 있는 경우dir-1)-모듈 외부에서 항상 액세스할 수 있습니다.

다음은 2개의 Java 모듈(GitHub의 소스 코드)의 예입니다.모듈 1은 다음 자원 파일로 구성됩니다.

├── dir-3
│   └── resource3.txt
├── dir1
│   └── resource1.txt
├── dir2
│   └── resource2.txt
└── root.txt

★★★★★★★★★★★★★★★★★」module-info.java:

module module_one {
  opens dir1;
}

모듈 2에는 모듈1이 필요합니다.module-info.java:

module module_two {
  requires module_one;
}

에는 다양한 자원 파일을 로드하기 위한 샘플메인 클래스가 있습니다

package module2;

import java.io.IOException;

public class Main {
  public static void main(String[] args) throws IOException {
    loadResource("root.txt", "From module's root directory");
    loadResource("dir1/resource1.txt", "From opened package `dir1`");
    loadResource("dir2/resource2.txt", "From internal package `dir2`");
    loadResource("dir-3/resource3.txt", "From directory `dir-3` with non-Java name");
  }

  public static void loadResource(String name, String comment) throws IOException {
    // module2 application class loader
    final var classLoader = Main.class.getClassLoader();
    try (var in = classLoader.getResourceAsStream(name)) {
      System.out.println();
      System.out.println("// " + comment);
      System.out.println(name + ": " + (in != null));
    }
  }
}

위의 클래스를 실행하면 다음 출력이 나타납니다.

// From module's root directory
root.txt: true

// From opened package `dir1`
dir1/resource1.txt: true

// From internal package `dir2`
dir2/resource2.txt: false

// From directory `dir-3` with non-Java name
dir-3/resource3.txt: true

디렉토리와 디렉토리에서 을 볼 수.dir-3디렉토리는 캡슐화되지 않기 때문에 모듈2는 그것들을 로드할 수 있습니다.

' ' ''dir1캡슐화되지만 무조건 열립니다.모듈 2도 로드할 수 있습니다.

' ' ''dir2캡슐화되어 열리지 않습니다.모듈 2에서 로드할 수 없습니다.

모듈 2에는 자체 리소스를 포함할 수 없습니다.dir1 ★★★★★★★★★★★★★★★★★」dir2이미 모듈1에 캡슐화되어 있기 때문입니다.추가하려고 하면dir1하다

Error occurred during initialization of boot layer
java.lang.LayerInstantiationException: Package dir1 in both module module_one and module module_two

참고로 Flyway 관련 문제가 있습니다.

언급URL : https://stackoverflow.com/questions/45166757/loading-classes-and-resources-in-java-9

반응형