인터페이스를 구현하는 Java 클래스 찾기
얼마 전 우연히 표준 Java 기능을 사용하여 특정 인터페이스를 구현한 클래스를 찾는 코드를 발견했습니다.함수가 논리적이지 않은 곳에 숨겨져 있다는 것은 알지만 패키지 이름에서 암시하는 것처럼 다른 클래스에 사용할 수 있습니다.그때는 필요 없었기 때문에 잊고 있었습니다만, 지금은 필요하게 되어 기능을 찾을 수 없게 되어 버렸습니다.이러한 기능은 어디에서 찾을 수 있습니까?
편집: IDE 기능이나 다른 기능을 찾는 것이 아니라 Java 어플리케이션 내에서 실행할 수 있는 기능을 찾고 있습니다.
얼마 전에 당신이 원하는 것을 할 수 있는 패키지와 더 많은 것을 준비했습니다(작성하는 유틸리티로 필요했습니다.ASM 라이브러리를 사용합니다.리플렉션을 사용할 수 있지만 ASM이 더 나은 것으로 나타났습니다.
웹 사이트의 오픈 소스 라이브러리에 패키지를 넣었습니다.도서관은 http://software.clapper.org/javautil/ 입니다.ClassFinder 클래스로 시작합니다.
제가 쓴 유틸리티는 지금도 매일 사용하는 RSS 리더기이기 때문에 코드가 실제로 사용되기 쉽습니다.ClassFinder를 사용하여 RSS 리더에서 플러그인 API를 지원합니다.시작 시 특정 인터페이스를 구현하는 클래스를 포함하는 jar 및 클래스 파일을 몇 개의 디렉토리 트리에서 검색합니다.생각보다 훨씬 빨라요.
라이브러리는 BSD 라이선스가 있으므로 안전하게 코드와 함께 묶을 수 있습니다.소스를 사용할 수 있습니다.
그게 당신에게 도움이 된다면, 마음대로 하세요.
업데이트: Scala를 사용하는 경우 이 라이브러리가 Scala에 더 적합합니다.
봄은 너를 위해 이것을 할 수 있어...
BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry();
ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr);
TypeFilter tf = new AssignableTypeFilter(CLASS_YOU_WANT.class);
s.addIncludeFilter(tf);
s.scan("package.you.want1", "package.you.want2");
String[] beans = bdr.getBeanDefinitionNames();
N.B. 올바른 결과를 얻으려면 TypeFilter가 중요합니다!여기서 제외 필터를 대신 사용할 수도 있습니다.
스캐너는 spring-context jar, 레지스트리는 spring-beans, 유형 필터는 spring-core에 있습니다.
나는 이것을 할 수 있는 반사 도서관이 정말 마음에 든다.
스캐너를 한다.getTypesAnnotatedWith
,getSubTypesOf
등)를 사용하여 자신의 것을 작성하거나 확장하거나 하는 것은 매우 간단합니다.
말씀하신 코드는 Java 1.3 이전부터 정의된 기능을 지원하기 위해 Java 6에서 도입된 것과 같습니다.퍼포먼스상의 이유로, 이것은 실행시에 인터페이스 실장을 검색하기 위한 권장 어프로치입니다.이전 버전의 Java에서의 지원이 필요한 경우는, 이 실장이 도움이 되었으면 합니다.
이전 버전의 Java에는 몇 가지 구현이 있지만 코어 API가 아닌 Sun 패키지로 구현됩니다(Image 내부 클래스도 있다고 생각합니다).이 기능을 하는 IO).코드는 단순하기 때문에 변경될 수 있는 비표준 Sun 코드에 의존하지 말고 자체 구현을 권장합니다.
패키지 레벨 주석
이 질문에 대한 답변은 이미 오래전에 이루어졌지만, 이 문제에 대한 또 다른 해결책은 패키지 레벨 주석을 사용하는 것입니다.
JVM의 모든 클래스를 찾는 것은 매우 어렵지만 패키지 계층을 참조하는 것은 매우 쉽습니다.
Package[] ps = Package.getPackages();
for (Package p : ps) {
MyAno a = p.getAnnotation(MyAno.class)
// Recursively descend
}
그런 다음 주석에서 클래스 배열의 인수를 지정합니다.그런 다음 특정 패키지의 package-info.java에 MyAno를 입력합니다.
사람들이 관심을 가지고 있다면 더 많은 세부사항(코드)을 추가할 것입니다만, 아마 아이디어를 얻을 수 있을 것입니다.
MetaInf 서비스 로더
@erickson 응답에 추가하려면 서비스 로더 방식을 사용할 수도 있습니다.Kohsuke는 서비스 로더 접근법에 필요한 META-INF를 생성하는 훌륭한 방법을 가지고 있습니다.
http://weblogs.java.net/blog/kohsuke/archive/2009/03/my_project_of_t.html
Extensible Component Scanner(extcos: http://sf.net/projects/extcos))를 사용하여 다음과 같은 인터페이스를 구현하는 모든 클래스를 검색할 수도 있습니다.
Set<Class<? extends MyInterface>> classes = new HashSet<Class<? extends MyInterface>>();
ComponentScanner scanner = new ComponentScanner();
scanner.getClasses(new ComponentQuery() {
@Override
protected void query() {
select().
from("my.package1", "my.package2").
andStore(thoseImplementing(MyInterface.class).into(classes)).
returning(none());
}
});
이 기능은 파일 시스템, jar 내 클래스 및 JBoss 가상 파일 시스템의 클래스에도 사용할 수 있습니다.또한 스탠드아론 어플리케이션 내에서는 물론 웹 또는 어플리케이션컨테이너 내에서도 동작하도록 설계되어 있습니다.
일반적으로 이 기능은 불가능합니다.Java ClassLoader 메커니즘은 특정 이름(pacakge 포함)의 클래스를 요구할 수 있는 기능만 보증하며 ClassLoader는 클래스를 제공할 수도 있고 해당 클래스를 모른다고 선언할 수도 있습니다.
클래스는 리모트서버에서 로딩할 수 있으며(많은 경우), 즉석에서 구축할 수도 있습니다.ClassLoader는 사용자가 요구하는 임의의 이름에 대해 특정 인터페이스를 구현하는 유효한 클래스를 반환하는 것이 전혀 어렵지 않습니다.그 인터페이스를 구현하는 클래스 목록은 길이가 무한합니다.
실제로 가장 일반적인 경우는URLClassLoader
파일 시스템 디렉토리 및 JAR 파일 목록에서 클래스를 검색합니다.그러니까 네가 필요한 건 이 모든 걸URLClassLoader
그 후, 이러한 디렉토리와 아카이브를 반복해, 거기에 있는 클래스 파일 마다, 대응하는 것을 요구해 주세요.Class
이의를 제기하고 그 반환을 훑어보다getInterfaces()
방법.
Class.isAssignableFrom()은 개별 클래스가 지정된 인터페이스를 구현하는지 여부를 나타냅니다.그래서 문제는 테스트할 수업 목록을 얻는 것이다.
제가 알기로는 Java에서 "잠재적으로 로드할 수 있는 클래스 목록"을 클래스 로더에 요청할 수 있는 직접적인 방법은 없습니다.따라서 사용자가 직접 보기 쉬운 항을 반복하고 Class.forName()을 호출하여 클래스를 로드한 후 테스트해야 합니다.
다만, 실제로 로드되고 있는 클래스에서 특정 인터페이스를 실장하고 있는 클래스를 알고 싶은 경우는, 조금 더 간단합니다.
- Java Instrumentation 프레임워크를 통해 Instrumentation.getAllLoadedClasses()를 호출할 수 있습니다.
- 리플렉션을 통해 특정 ClassLoader의 ClassLoader.classes 필드를 쿼리할 수 있습니다.
instrumentation 기술을 사용하면 (링크의 설명에 따라) JVM이 시작될 때 기본적으로 "에이전트" 클래스가 호출되어 Instrumentation 개체를 전달하게 됩니다.이 때 정적 필드에 "나중에 저장"한 후 나중에 기본 응용 프로그램 코드가 호출하여 로드된 클래스 목록을 가져오도록 할 수 있습니다.
실행 중인 프로그램에서 이 문제를 해결하려면 java.lang.* 패키지를 고려해야 합니다.Class 객체를 취득한 경우 isAssignableFrom 메서드를 사용하여 다른 클래스의 인터페이스인지 여부를 확인할 수 있습니다.
이클립스 같은 툴은 이러한 정보를 쉽게 검색할 수 있는 기능이 없습니다.
테스트할 클래스 객체의 특정 목록이 없는 경우 ClassLoader 객체를 참조하여 getPackages() 메서드를 사용하여 자체 패키지 계층 반복기를 구축할 수 있습니다.
다만, 이러한 메서드나 클래스는 꽤 느릴 수 있습니다.
언급URL : https://stackoverflow.com/questions/435890/find-java-classes-implementing-an-interface
'it-source' 카테고리의 다른 글
JavaScript에서의 MD5 구현 속도 향상 (0) | 2022.10.20 |
---|---|
Java에서 UUID의 최상위 비트를 사용한 충돌 가능성 (0) | 2022.10.20 |
python의 루프에 대해 첫 번째 엔트리를 건너뛰시겠습니까? (0) | 2022.10.20 |
intXX_t와 int_fastXX_t의 차이점은 무엇입니까? (0) | 2022.10.20 |
uuid v4 대 v6(순서 완료), MySQL에서 더 효율적인 것은 무엇입니까? (0) | 2022.10.20 |