通过自定义注释注入常量

时间:2015-03-22 16:53:20

标签: java annotations lombok

我的代码中有一堆常量用于我系统的各种可调属性。我将所有这些文件移到中央.properties文件中。我目前的解决方案是使用一个Properties.java静态加载.properties文件并公开各种getter方法,如下所示:

public class Properties {
    private static final String FILE_NAME = "myfile.properties";
    private static final java.util.Properties props;

    static {
        InputStream in = Properties.class.getClassLoader().getResourceAsStream(
                FILE_NAME);
        props = new java.util.Properties();
        try {
            props.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getString(Class<?> cls, String key) {
        return props.getProperty(cls.getName() + '.' + key);
    }

    public static int getInteger(Class<?> cls, String key) {
        return Integer.parseInt(getString(cls, key));
    }

    public static double getDouble(Class<?> cls, String key) {
        return Double.parseDouble(getString(cls, key));
    }
}

唯一的问题是,对于我从这个文件得到的每个常量,我都有一些样板:

private final static int MY_CONSTANT = Properties.getInteger(
    ThisClass.class, "MY_CONSTANT");

我认为我不想使用Spring之类的东西,因为这似乎更像是一个锅炉。我希望使用自定义注释来解决问题。我找到了this tutorial,但我无法理解如何从注释处理中获得我想要的功能。 Java文档甚至没那么有用。不过,这应该是我在编译时应该做的事情。我知道班级和领域的名字。

我的想法是这样的:

@MyAnnotation
private static final int MY_CONSTANT;

任何人都知道我会如何做这个或至少是我想要做的最佳做法?

2 个答案:

答案 0 :(得分:2)

首先,你不应该这样做。它很实用,但太过于hacky,如果你想用不同的设置编写测试,你就会遇到问题。而且,没有人会理解它是如何运作的。

注释处理器可能对您无能为力。龙目岛风格的黑客处理器可以。你想做

@MyAnnotation
private static final int MY_CONSTANT;

一样工作
private final static int MY_CONSTANT =
    Properties.getInteger(ThisClass.class, "MY_CONSTANT");

原始表达式没有编译(由于未初始化的最终变量),但它解析得很好,而Lombok可以完成它的工作。那里已经有相关的东西了:

实际上,你可以只写

@MyAnnotation
int MY_CONSTANT;

并让你的注释也改变修饰符。我要查看@UtilityClass的{​​{3}}和eclipse处理程序,我想你需要的只是生成初始值设定项(因为它全部都是有效的)该死的很复杂)。

我不认为龙目岛本身会很快实现这一点,因为

  • 所有static内容都是不可测试的,而且大多数都是错误的样式
  • 并非所有人都希望在他们的代码中使用
  • 它没有那么多样板
  • 它也神奇地引用了课程Properties,但这可以通过javac
  • 解决

但我想可能会接受一个贡献。

答案 1 :(得分:1)

实际上并不十分清楚为什么以及您希望存档的内容。

正如我正确指出的那样,您希望使用特殊类型的注释自动为某些static final文件中的properties常量赋值。不幸的是这是不可能的没有特殊的黑客攻击。注释与此无关。

原因是必须初始化final个字段并且它是编译器的请求。 java中没有特殊的注释可以提供你想要的语法糖。

但如果你坚持这个,有两种方法:

  1. Extrim方式。使用默认值初始化所有属性字段。然后在某些static初始化部分中使用this hack使用reflection机制初始化此值,并通过读取properties中的值进行编码。

  2. 不那么简单的方法:拒绝final修饰符对属性字段的请求,并仅使用reflection填充这些字段值。

  3. 此外,对于这些方式,是的,您可以使用注释。但您必须解决以下技术问题:

    1)查找classpath中所有类中的所有字段,这些字段都使用特殊annotation进行注释。看着: Get all of the Classes in the ClasspathGet list of fields with annotation, by using reflection

    2)强制您的Properties课程在应用程序的所有可能输入点初始化。在此类的静态部分中,您将加载属性文件,然后使用带有反射和类加载器的(1)方法,为所有常量赋值。