Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Java Annotations help me with this?

I'm wondering if there is a way to specify that a method gets called in advance of a class method. I know something like this should be posssible, since JUnit has before(), what I want to do is similar.

Here is a concrete example of what I'd like to do

class A {

 public void init(int a) {
  System.out.println(a);
 }

 @magic(arg=1)
 public void foo() { 
   //
 }

 public static void main() {
   A a = new A();
   a.foo();
 }
}

//Output: 1

Basically I want an annotation to tell either the compiler or the jvm call init() before foo()

like image 347
Mike Avatar asked Sep 22 '09 13:09

Mike


People also ask

What is annotation in Java?

Java Annotation is a tag that represents the metadata i.e. attached with class, interface, methods or fields to indicate some additional information which can be used by java compiler and JVM.

How do you mark a method as annotated in Java?

Any declaration can be marked with annotation by placing it above that declaration. As of Java 8, annotations can also be placed before a type. 1. Above declarations As mentioned above, Java annotations can be placed above class, method, interface, field, and other program element declarations.

How do I make an annotation repeatable in Java?

For an annotation to be repeatable it must be annotated with the @Repeatable annotation, which is defined in the java.lang.annotation package. Its value field specifies the container type for the repeatable annotation.

How do you interpret annotation in JVM?

Annotations can be interpreted by compiler or IDE at compile time or by JVM at runtime. Annotations can be used to show attributes of an element: e.g. @Deprecated, @Override, or @NotNull to describe the purpose of an element of the framework, e.g. @Entity, @TestCase, @WebService


1 Answers

If you have interface A you can wrap instances of this interface with Proxy and inside invoke method of its InvocationHandler you are free to check whether method is annotated and perform some actions depending on that:

class Initalizer implements InvocationHandler {
    private A delegate;
    Initializer(A delegate) {
        this.delegate = delegate;
    }

    public Object invoke(Object proxy, Method method, Object[] args) {
        if (method.isAnnotationPresent(magic.class)) {
            magic annotation = method.getAnnotation(magic.class);
            delegate.init(magic.arg);
        }
        method.invoke(delegate, args);
    }
} 
A realA = ...;
A obj = Proxy.newProxyInstance(A.class.getClassLoader(), new Class[] {A.class}, new Initializer(realA));

Or you can try using "before" advice of AspectJ. It will be something like the next:

@Aspect
public class Initializer {
    @Before("@annotation(your.package.magic) && target(obj) && @annotation(annotation)")
    private void initialize(A obj, magic annotation) {             
         a.init(annotation.arg);
    }
}

I'm not sure that snippets are working, they just illustrate idea.

like image 113
Rorick Avatar answered Oct 24 '22 17:10

Rorick