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()
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With