Constant Injection Using Custom Annotation

I have a bunch of constants in my code for various custom properties of my system. I move all of them to a central .properties file. My current solution is to have one Properties.java that statically loads the .properties file and provides various getter methods as follows:

 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)); } } 

The only problem is that for every constant I get from this file, I have a template:

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

I don’t think I want to use Spring or the like, as it looks like even more collapses. I was hoping to use custom annotation to solve the problem. I found this tutorial , but I can't figure out how to get the functionality that I want from annotation processing. Java docs were even less useful. This should be what I would have to do at compile time. I know the class names and fields.

What I think looks something like this:

 @MyAnnotation private static final int MY_CONSTANT; 

Does anyone know how I will do this, or at least the best practices for what I want to do?

+6
source share
2 answers

First of all, you should not do this. This is practical, but too shitty, and if you ever want to write a test using different settings, you will have problems. Moreover, no one will understand how this works.

An annotation handler may not do anything for you. Lombok-style hack processor can. You want to do

 @MyAnnotation private static final int MY_CONSTANT; 

works like

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

The original expression does not compile (due to the uninitialized final variable), but it is well understood, and Lombok can do its job. There is already something there:

So you could only write

 @MyAnnotation int MY_CONSTANT; 

and let your annotation change the modifiers too. I would look at the eclipse and javac handlers for @UtilityClass , I think all you need to do is generate an initializer (which is pretty complicated, because it's all complicated).

I do not think that Lombok himself will implement this in the near future, since

  • all static material is not tested and basically bad style
  • and not everyone wants this in their code
  • These are not many patterns.
  • it also magically belongs to the Properties class, but this can be solved using configuration

but I think the contribution can be accepted.

+2
source

Actually, it’s not entirely clear why and why you are archiving.

As I understand correctly, you want to use special annotations to automatically assign values ​​for static final constants from some properties file. Unfortunately, it is impossible without special hacks. And annotations have nothing to do with this.

The reason is that the final fields must be initialized and this is a compiler request. There are no special annotations in java that will provide the syntactic sugar you want.

But if you insist on it, there are two ways:

  • Extreme Initialize all property fields with a default value. Then, using this hack in some static initialization section, initialize this value using the reflection mechanism, and you encode the read values ​​from properties .

  • Less extrim way: refuse to request final modifiers for property fields and use only reflection fill these field values.

Also, for these methods, yes, you can use annotations. But you have to solve the following technical problems:

1) Find all fields in all classes in the pathpath that are annotated with a special annotation . Look at: Get all classes on the way to classes and Get a list of fields with annotation using reflection

2) Make your properties class initialize at all possible input points of your application. In the static section of this class, you upload your properties file, and then, using the (1) method with reflection and the class loader, assign values ​​to all constants.

+1
source

Source: https://habr.com/ru/post/984108/


All Articles