如何搜索带注释类的整个类路径?
我正在创建一个库,希望允许用户注释他们的类,因此当Web应用程序启动时,我需要扫描整个类路径以查找某些注释。
我正在考虑类似于Java EE 5 Web服务或EJB的新功能。你用@WebService或@EJB注释你的类,系统会在加载时找到这些类,这样就可以远程访问它们。
如何搜索带注释类的整个类路径?
我正在创建一个库,希望允许用户注释他们的类,因此当Web应用程序启动时,我需要扫描整个类路径以查找某些注释。
我正在考虑类似于Java EE 5 Web服务或EJB的新功能。你用@WebService或@EJB注释你的类,系统会在加载时找到这些类,这样就可以远程访问它们。
当前回答
另一个解决方案是朗玛莫的倒影。
快速回顾一下:
如果您正在使用Spring,那么Spring解决方案是最好的选择。否则就是很大的依赖。 直接使用ASM有点麻烦。 直接使用Java Assist也很笨拙。 注释超轻,方便。还没有专家集成。 Reflections索引所有东西,而且非常快。
其他回答
另一个解决方案是朗玛莫的倒影。
快速回顾一下:
如果您正在使用Spring,那么Spring解决方案是最好的选择。否则就是很大的依赖。 直接使用ASM有点麻烦。 直接使用Java Assist也很笨拙。 注释超轻,方便。还没有专家集成。 Reflections索引所有东西,而且非常快。
反射似乎比Spring快得多。找到了解决这一差异的特性请求:http://www.opensaga.org/jira/browse/OS-738
这就是为什么在开发过程中使用reflection作为应用程序的启动时间是非常重要的。对于我的用例来说,Reflections似乎也很容易使用(找到一个接口的所有实现者)。
如果你想要一个真正轻量级(没有依赖,简单的API, 15 kb的jar文件)和非常快速的解决方案,可以看看https://github.com/rmuller/infomas-asl上的注释检测器
声明:我是作者。
现在回答还来得及吗? 我想说,最好使用类库,如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 ClassPathScanningCandidateComponentProvider没有发现接口。