如何搜索整个类路径以查找已注释的类?
我正在编写一个库,希望允许用户注释他们的类,因此当Web应用程序启动时,我需要扫描整个类路径以查找特定的注释。
我考虑使用Java EE 5 Web Services或EJB的新功能。您可以使用@WebService
或@EJB
对类进行注释,系统会在加载时找到这些类,因此可以远程访问它们。
如何搜索整个类路径以查找已注释的类?
我正在编写一个库,希望允许用户注释他们的类,因此当Web应用程序启动时,我需要扫描整个类路径以查找特定的注释。
我考虑使用Java EE 5 Web Services或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());
还有另一种解决方案是ronmamo的Reflections。
快速回顾:
new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)
。 - zappClassIndex.getAnnotated(com.test.YourCustomAnnotation.class)
有一个很棒的评论是由zapp提出的,它包含在所有这些答案中:
new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)
Spring有一个称为AnnotatedTypeScanner
类的东西。
这个类内部使用了
ClassPathScanningCandidateComponentProvider
该类包含实际扫描类路径资源的代码。它通过在运行时使用可用的类元数据来实现这一点。
您可以简单地扩展此类或使用相同的类进行扫描。以下是构造函数定义。
/**
* Creates a new {@link AnnotatedTypeScanner} for the given annotation types.
*
* @param considerInterfaces whether to consider interfaces as well.
* @param annotationTypes the annotations to scan for.
*/
public AnnotatedTypeScanner(boolean considerInterfaces, Class<? extends Annotation>... annotationTypes) {
this.annotationTypess = Arrays.asList(annotationTypes);
this.considerInterfaces = considerInterfaces;
}
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;
}
}
Class<?> clazz = AnnotationUtils.findAnnotationDeclaringClass(Target.class, null);
null
值作为第二个参数(用于定义 Spring 将在继承层次结构中扫描使用注解的类的类),那么根据实现,你会始终得到一个 null
返回值。 - jonashackt
@Conditional
注释进行评估和操作。因此,如果一个类的@Conditional
值返回false,则它不会被findCandidateComponents
返回,即使它与扫描器的过滤器匹配。这让我今天感到困惑 - 我最终使用了下面Jonathan的解决方案。 - Adam BurleyBeanDefinition
对象没有直接获取类的方法。最接近的方法似乎是getBeanClassName
,它返回一个完全限定的类名,但这个方法的确切行为不清楚。此外,也不清楚类是在哪个类加载器中找到的。 - MaxClass<?> cl = Class.forName(beanDef.getBeanClassName());
,来源是http://farenda.com/spring/find-annotated-classes/。 - James Watkins