java - 无法从 Java 类获取自定义注解
问题描述
我想从 Java 类中获取类级别的注释:
class FixAnnotation {
public String[] author;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Fix {
public String[] author() default "";
}
我试过这个编译的java类的例子:
@Component("test")
@Fix(
author = {"Example author 1", "Example author 2"}
)
public class Order implements Action {
..
}
但是当我尝试时:
公共列表 listLocalFilesAndDirsAllLevels(File baseDir) {
List<File> collectedFilesAndDirs = new ArrayList<>();
Deque<File> remainingDirs = new ArrayDeque<>();
if(baseDir.exists()) {
remainingDirs.add(baseDir);
while(!remainingDirs.isEmpty()) {
File dir = remainingDirs.removeLast();
List<File> filesInDir = Arrays.asList(dir.listFiles());
for(File fileOrDir : filesInDir) {
// We need to process only .class files
if(fileOrDir.getName().endsWith(".class")){
collectedFilesAndDirs.add(fileOrDir);
if(fileOrDir.isDirectory()) {
remainingDirs.add(fileOrDir);
}
}
}
}
}
return collectedFilesAndDirs;
}
List<File> list;
for(int i=0; i<list.size(); i++) {
File item = list.get(i);
System.out.println(item.getName());
Fix name = item.getClass().getAnnotation(Fix.class);
out.println("author: " + name.author());
}
我得到NPE。你知道我怎样才能得到注释内容吗?
编辑:我试过这个:
public static void main() throws Exception
{
final File folder = new File("/opt/test");
processAnnotatedFiles(listLocalFilesAndDirsAllLevels(folder));
}
public void processAnnotatedFiles(List<File> list) throws IOException, ClassNotFoundException {
out.println("Directory files size " + list.size());
for(int i=0; i<list.size(); i++) {
out.println("File " + list.get(i).getName());
File file = list.get(i);
String path = file.getPath();
String[] authors = getFixFromClassFile(Paths.get(path));
System.out.println(Arrays.toString(authors));
}
}
public List<File> listLocalFilesAndDirsAllLevels(File baseDir) {
List<File> collectedFilesAndDirs = new ArrayList<>();
Deque<File> remainingDirs = new ArrayDeque<>();
if(baseDir.exists()) {
remainingDirs.add(baseDir);
while(!remainingDirs.isEmpty()) {
File dir = remainingDirs.removeLast();
List<File> filesInDir = Arrays.asList(dir.listFiles());
for(File fileOrDir : filesInDir) {
// We need to process only .class files
if(fileOrDir.getName().endsWith(".class")){
collectedFilesAndDirs.add(fileOrDir);
if(fileOrDir.isDirectory()) {
remainingDirs.add(fileOrDir);
}
}
}
}
}
return collectedFilesAndDirs;
}
private String[] getFixFromClassFile(Path pathToClass) throws MalformedURLException, ClassNotFoundException {
// Create class loader based on path
URLClassLoader loader = new URLClassLoader(new URL[]{pathToClass.toUri().toURL()});
// convert path to class with package
String classWithPackage = getClassWithPackageFromPath(pathToClass);
// Load class dynamically
Class<?> clazz = loader.loadClass(classWithPackage);
Fix fix = clazz.getAnnotation(Fix.class);
if (fix == null) {
return new String[0];
}
return fix.author();
}
private String getClassWithPackageFromPath(Path pathToClass) {
final String packageStartsFrom = "com.";
final String classFileExtension = ".class";
final String pathWithDots = pathToClass.toString().replace(File.separator, ".");
return pathWithDots.substring(pathWithDots.indexOf(packageStartsFrom)).replace(classFileExtension, "");
}
我明白了java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1927)
解决方案
当您getClass
在对象上调用方法时File
,它将返回java.io.File
Class
实例。此方法不会从给定文件加载类。
如果要从给定*.class
文件加载类,则需要使用java.lang.ClassLoader
实现。例如,java.net.URLClassLoader
。您可以在下面找到如何加载类和检查注释的示例:
import java.io.File;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
@Fix(author = "Test author")
public class ReflectionApp {
public static void main(String[] args) throws Exception {
String path = "path/to/com/so/ReflectionApp.class";
String[] authors = getFixFromClassFile(Paths.get(path));
System.out.println(Arrays.toString(authors));
}
private static String[] getFixFromClassFile(Path pathToClass) throws MalformedURLException, ClassNotFoundException {
// Create class loader based on path
URLClassLoader loader = new URLClassLoader(new URL[]{pathToClass.toUri().toURL()});
// convert path to class with package
String classWithPackage = getClassWithPackageFromPath(pathToClass);
// Load class dynamically
Class<?> clazz = loader.loadClass(classWithPackage);
Fix fix = clazz.getAnnotation(Fix.class);
if (fix == null) {
return new String[0];
}
return fix.author();
}
private static String getClassWithPackageFromPath(Path pathToClass) {
final String packageStartsFrom = "com.";
final String classFileExtension = ".class";
final String pathWithDots = pathToClass.toString().replace(File.separator, ".");
return pathWithDots.substring(pathWithDots.indexOf(packageStartsFrom)).replace(classFileExtension, "");
}
}
上面的代码打印:
[Test author]
也可以看看:
推荐阅读
- java - 使用 lamda 表达式查询 concat 字符串到数组
- node.js - 如何在类验证器和类转换器中验证和转换数字数组或数字数组
- javascript - 无法使用 Javascript 比较两个 ISO 格式日期
- r - 用于数据可视化的 PCA 与 t-SNE:有没有办法用 t-SNE 加载图?
- c - 如何使用本机 qsort 在 C 中对“int **”数组进行排序
- java - 使用动态编程在java中拆分字符串
- python - 旧媒体文件可见,但在 django 开发管理控制台上上传的新图像文件失败,找不到 404
- django - 无效的语法几乎尝试了一切
- r - 使用 forcats 和 purrr 总结字符向量列表
- python - 如何在python中将三列合并为一列