本文介绍了如何使用注释处理器编写包中所有内容的名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标是让 Java 应用程序在运行时访问其中一个包中包含的所有资源的列表.用例:在包中包含纯文本属性的文件,应用需要访问这些属性才能完成任务.

The goal is for a Java app to access a list of all the resources contained in one of its packages, at run time. The use case: files containing properties in plain text in a package, that need to be accessed by the app to do its thing.

答案(https://stackoverflow.com/a/67092012/798502)表明注释可能是要走的路.应用程序应该能够在编译时创建一个文本文件,列出给定包的内容名称,使用注释处理器.在运行时,应用程序将访问此名称列表,因此能够遍历并访问此内容.我已经浏览过这种方法,但找不到方法,这就是为什么我不在这里提供代码示例.

An answer (https://stackoverflow.com/a/67092012/798502) indicates that annotations could be the way to go. The app should be able to create at compile time a text file listing the names of the contents of a given package, using annotation processors. At run time, the app would access this list of names and would hence be able to walk through and access this content.I have browsed about this approach but could not find a way, this is why I don't provide a code sample here.

推荐答案

这个任务有两个完全不相关的部分:

There are two utterly unrelated parts to this task:

  1. 编译时方面:如何创建和维护列出资源的文本文件.

  1. The compile-time aspect: How to create and maintain the text file(s) that list the resources.

运行时方面:如何读取这些文件.

The run-time aspect: How to read these files.

注释处理器只是解决第一个问题的一种方法.简单的方法是自己编写这些文本文件.这很好用而且很简单.唯一的缺点是额外的工作:如果您创建一个新资源,您必须记住也将其放入文本文件中,否则您的系统根本不会选择它作为现有资源.

Annotation Processors are just one way to solve the first problem. The simple way is to just write these text files yourself. This works fine and is simple. The only downside is the extra work: If you make a new resource you have to remember to also put it in the text file, or it isn't picked up by your system as existing at all.

当我们谈论作为资源的类时(例如,您有一个名为 Shield 的抽象类和一大堆代表具有各种独特属性的盾牌的类,并且您添加了另一个有趣的盾牌对于您的游戏的新版本),那么该类来自源代码,然后可以使用注释处理器来自动生成和维护列出屏蔽类的文本文件.

When we're speaking about classes as resources (for example, you have an abstract class named Shield and a whole bunch of classes that represent shields with various unique properties, and you add another fun shield for a new release of your game), then that class comes from source code, and then an annotation processor can be used to generate and maintain the text file listing the shield classes automatically.

如果我们不是在谈论类,注释处理器在这里没有任何意义.

If we're not talking about classes, annotation processors do not make any sense whatsoever here.

即使我们在谈论课程,也只是为了方便.您也可以手动编写这些文件.Annotation Processors 只是为您提供了一种让您的代码库具有以下属性的方法:您只需.. 制作一个新的 class InvulnerabilityGrantingShield extends Shield,用例如注释它@Provides(Shield.class),然后自动出现列出所有屏蔽类的文本文件.这就是它会做的所有事情.方便.仅此而已.

Even if we are talking classes, it's just a convenience. You can also manually write these files. Annotation Processors simply give you a way to have your codebase have the following property: You just.. make a new class InvulnerabilityGrantingShield extends Shield, annotate it with e.g. @Provides(Shield.class), and then the text file listing all shield classes just happens, automatically. That's all it would do. Convenience. Nothing more.

如果我们谈论的是非类,您可以考虑构建系统插件,其功能相当于:

If we're talking non-classes, you could consider build system plugins that do the equivalent of:

ls src/main/resources/icons/*.png > build/icons/list_of_all_icons.txt

作为构建的一部分.如果可以的话,您必须查找构建系统的文档;我认为大多数不能.

as part of the build. You'll have to look up the docs of your build system if it can do that; I gather that most cannot.

在运行时,如果资源是类,你需要做的就是使用baked-into-java ServiceLoader.

At run-time, all you need to do if the resources are classes, is to use the baked-into-java ServiceLoader.

如果它们不是类,则您必须自己编写.这与注释处理器没有任何关系 - 只是为了制作文本文件,而不是为了阅读它们.

If they aren't classes, you'd have to write this yourself. This has nothing whatsoever to do with annotation processors - that is JUST for making the text files, not for reading them.

这样做相当容易:

ClassLoader loader = MyClass.class.getClassLoader();
Enumeration<URL> resources = loader.getResources("icons/all_icons.txt");
while (resources.hasMoreElements()) {
    URL url = resource.nextElement();
    try (InputStream in = url.openStream()) {
        for (String line : new String(in.readAllBytes(), StandardCharsets.UTF_8).split("\\R")) {

            line = line.trim();
            if (line.isEmpty() || line.startsWith("#")) continue;
            URL res = loader.getResource(line);
            loadTheResource_WriteThisYourself(res);
        }
    }
}

这篇关于如何使用注释处理器编写包中所有内容的名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 13:33