Attributes in Java annotations have to be completely static expressions, but since the language lacks pre-processing capability, code reuse in annotations are basically non-existent.

For example, there are no alternative for the following use cases:

#define GRANTED {"group1", "group2"}

@Access(granted = GRANTED)
public void ...

#define USER_HAS_ACCESS(userArg, permissions) "arguments." + userArg + ".hasAccess(" + permissions + ")"

@Access(grantedIf = USER_HAS_ACCESS("usr", "modify"))
public void modifyData(User usr, Data d) ...

In these cases the code replaced by the macro must be re-produced at each location the annotation is used (as there are no array constants and no compile-time string formatting in Java), which is a big maintenance problem.

I am wondering is there any Java pre-processor that works well with Maven?

有帮助吗?

解决方案

you can try my preprocessor https://github.com/raydac/java-comment-preprocessor it supports maven example (not the most optimal solution but it works)

package com.mycompany.mavenproject1;

//#local GRANTED="\"new\")"

@Anno(/*$GRANTED$*//*-*/"default to be used without preprocessor")
public class App 
{

    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}

其他提示

Mind you, if annotation content is static, it can however be rather complicated. indeed, annotation content can be

  • string
  • enum
  • Number
  • another annotation
  • or even an array

Which lead to some kind of annotation hell (I'm thinking, as an example, about JPA named queries).

Furthermore, as what you are asking for reminds me strongly of EJB security model, I will take some more examples.

An EJB can be freely acessed by any user (using ... nothing, it's the default), or its access can be restricted to some roles, using the @RolesAllowed({"roleA", "roleB", "roleC"}). Furthermore, as the strings used here are simply Java constants, they can be declared in a "constants interface", declaring only those roles

public interface Roles {
    String ROLE_A = "roleA";
    String ROLE_B = "roleB";
    String ROLE_C = "roleC";
}

Then, my initial declaration becomes @RolesAllowed({Roles.ROLE_A, Roles.ROLE_B, Roles.ROLE_C}). This is however do not detail how these roles are applied to users ... which lead us right into the JAAS hell (an hell in which I won't push you down to ... well, unless you want to get rid of your preprocessor idea - which sits in another circle of hell :-)).

Anyway, let me stand one point very clearly : annotations are simply declarative, and they can/should only contain declaration of intention, and not behaviour. You can of course do string parsing to detect content and operate the require behaviour, but it's specifically a bad idea. If you're absolutely convinced you need your preprocessor, please at least replace the string fragment by another annotation :

#define USER_HAS_ACCESS(userArg, permissions) @Allow(userName=userArg, granted=permissions)

But ... wait, I've declared an annotation to simplify that preprocessing ? Maybe is it beceause those two things are greatly overlaping :-) So much, in fact, that it's some common sense to have annotation declared in a superclass and applied to all its descendant classes ...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top