주석이 달린 클래스의 전체 클래스 경로를 검색하는 가장 좋은 방법은 무엇입니까?
라이브러리를 만들고 있는데 사용자가 클래스에 주석을 달 수 있도록 웹 응용 프로그램이 시작될 때 특정 주석에 대해 전체 클래스 경로를 스캔해야합니다.
이 작업을 수행 할 라이브러리 또는 Java 기능을 알고 있습니까?
편집 : Java EE 5 웹 서비스 또는 EJB의 새로운 기능과 같은 것을 생각하고 있습니다. 당신은 당신의 클래스에 주석 @WebService
또는 @EJB
그들이 원격으로 액세스 할 수있는 로딩 그렇게하는 동안 시스템은 이러한 클래스를 찾습니다.
답변
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider를 사용하십시오.
API
기본 패키지에서 클래스 경로를 스캔하는 구성 요소 제공자. 그런 다음 후보를 찾기 위해 결과 클래스에 제외 및 포함 필터를 적용합니다.
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFALT_FILTER>);
scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class));
for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>))
System.out.println(bd.getBeanClassName());
답변
또 다른 해결책은 Google 반영입니다. 입니다.
빠른 검토:
- Spring 솔루션은 Spring을 사용하는 경우 갈 수있는 방법입니다. 그렇지 않으면 큰 의존성입니다.
- ASM을 직접 사용하는 것은 다소 번거 롭습니다.
- Java Assist를 직접 사용하는 것도 복잡합니다.
- Annovention은 매우 가볍고 편리합니다. 아직 maven 통합이 없습니다.
- Google 리플렉션은 Google 컬렉션을 끌어냅니다. 모든 것을 색인화 한 다음 매우 빠릅니다.
답변
ClassGraph를 사용하여 주어진 주석이있는 클래스를 찾을 수있을 뿐만 아니라 다른 관심있는 기준 (예 : 주어진 인터페이스를 구현하는 클래스)을 검색 할 수 있습니다. (면책 조항, ClassGraph의 저자입니다.) ClassGraph는 전체 클래스 그래프 (모든 클래스, 주석, 메소드, 메소드 매개 변수 및 필드)를 메모리, 클래스 경로의 모든 클래스 또는 클래스의 추상 표현을 작성할 수 있습니다 허용 된 패키지를 사용하면 원하는 클래스 그래프를 쿼리 할 수 있습니다. ClassGraph는 다른 스캐너보다 더 많은 클래스 경로 지정 메커니즘 및 클래스 로더를 지원 하며 새로운 JPMS 모듈 시스템과도 원활하게 작동하므로 ClassGraph를 기반으로 코드를 작성하면 코드를 최대한 이식 할 수 있습니다. 여기 API를 참조하십시오.
답변
매우 가볍고 (종속성, 간단한 API, 15kb jar 파일) 매우 빠른 솔루션 을 원한다면 https://github.com/rmuller/infomas-asl 에서 annotation-detector
찾아 보십시오.
면책 조항 : 나는 저자입니다.
답변
Java Pluggable Annotation Processing API를 사용하여 컴파일 프로세스 중에 실행될 주석 프로세서를 작성할 수 있으며 주석이 달린 모든 클래스를 수집하고 런타임에 사용할 색인 파일을 빌드합니다.
런타임에 클래스 경로를 스캔 할 필요가 없기 때문에 어노테이션이있는 클래스 발견을 수행 할 수있는 가장 빠른 방법입니다. 이는 일반적으로 매우 느린 조작입니다. 또한이 방법은 모든 클래스 로더에서 작동하며 일반적으로 런타임 스캐너에서 지원되는 URLClassLoader와 함께 작동합니다.
위의 메커니즘은 이미 ClassIndex 라이브러리 에서 구현되었습니다 .
이를 사용하려면 @IndexAnnotated 메타 주석으로 사용자 정의 주석에 주석을 달 수 있습니다 . 이렇게하면 컴파일시 색인 파일 인 META-INF / annotations / com / test / YourCustomAnnotation이 주석이 달린 모든 클래스를 나열합니다. 다음을 실행하여 런타임시 인덱스에 액세스 할 수 있습니다.
ClassIndex.getAnnotated(com.test.YourCustomAnnotation.class)
답변
대답하기에 너무 늦었습니까? 나는 도서관에가는 것이 더 낫습니다.ClassPathScanningCandidateComponentProvider 또는 Scannotations 와 같은 좋습니다.
그러나 누군가 누군가 classLoader를 사용 해보고 싶더라도 패키지의 클래스에서 주석을 인쇄하기 위해 직접 작성했습니다.
public class ElementScanner {
public void scanElements(){
try {
//Get the package name from configuration file
String packageName = readConfig();
//Load the classLoader which loads this class.
ClassLoader classLoader = getClass().getClassLoader();
//Change the package structure to directory structure
String packagePath = packageName.replace('.', '/');
URL urls = classLoader.getResource(packagePath);
//Get all the class files in the specified URL Path.
File folder = new File(urls.getPath());
File[] classes = folder.listFiles();
int size = classes.length;
List<Class<?>> classList = new ArrayList<Class<?>>();
for(int i=0;i<size;i++){
int index = classes[i].getName().indexOf(".");
String className = classes[i].getName().substring(0, index);
String classNamePath = packageName+"."+className;
Class<?> repoClass;
repoClass = Class.forName(classNamePath);
Annotation[] annotations = repoClass.getAnnotations();
for(int j =0;j<annotations.length;j++){
System.out.println("Annotation in class "+repoClass.getName()+ " is "+annotations[j].annotationType().getName());
}
classList.add(repoClass);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* Unmarshall the configuration file
* @return
*/
public String readConfig(){
try{
URL url = getClass().getClassLoader().getResource("WEB-INF/config.xml");
JAXBContext jContext = JAXBContext.newInstance(RepositoryConfig.class);
Unmarshaller um = jContext.createUnmarshaller();
RepositoryConfig rc = (RepositoryConfig) um.unmarshal(new File(url.getFile()));
return rc.getRepository().getPackageName();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
그리고 설정 파일에서 패키지 이름을 넣고 클래스에 정렬 해제하십시오.
답변
Spring에서는 AnnotationUtils 클래스를 사용하여 다음을 작성할 수도 있습니다. 즉 :
Class<?> clazz = AnnotationUtils.findAnnotationDeclaringClass(Target.class, null);
자세한 내용과 다른 모든 방법은 공식 문서를 확인하십시오 :
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationUtils.html