Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Annotations and apt (fundamentals)

I'm really rolling up my sleeves and trying to understand Java annotations for the first time, and have read the Sun, Oracle and Wikipedia articles on the subject. They're easy to understand conceptually, but am finding it difficult putting all the pieces of the puzzle together.

The following example is probably terrible engineering, but just humor me (it's an example!).

Let's say I have the following class:

public Widget
{
    // ...

    public void foo(int cmd)
    {
        switch(cmd)
        {
        case 1:
            function1();
            break;
        case 2:
            function2();
            break;
        case 3:
        default:
            function3();
            break;
        }
    }
}

Now, somewhere else in my project, I have another class, SpaceShuttle, that has a method called blastOff():

public class SpaceShuttle
{
    // ...

    public void blastOff()
    {
        // ...
    }
}

Now then, I want to configure an annotation called Widgetize so that any methods annotated with @Widgetize will have Widget::foo(int) invoked prior to their own call.

@interface Widgetize
{
    int cmd() default 2;
}

So now let's revisit SpaceShuttle:

public class SpaceShuttle
{
    // ...

    @Widgetize(3)
    public void blastOff()
    {
        // Since we pass a cmd of "3" to @Widgetize,
        // Widget::function3() should be invoked, per
        // Widget::foo()'s definition.
    }
}

Alas, my questions!

  1. I assume that somewhere I need to define an annotation processor; a Java class that will specify what to do when @Widgetize(int) annotations are encountered, yes? Or does this happen in, say, XML config files that get fed into apt (like the way ant reads build.xml files)?

  2. Edit: If I was correct about these annotation processors in question #1 above, then how do I "map"/"register"/make known these processors to the apt?

  3. In buildscripts, is apt typically ran before javac, so that annotation-based changes or code generation takes place prior to the compile? (This is a best practices-type question).

Thanks and I apologize for my code samples, they turned out a lot bulkier than I intended them to (!)

like image 455
Eugie Avatar asked Jan 28 '11 15:01

Eugie


People also ask

What is annotations in Java?

In the Java computer programming language, an annotation is a form of syntactic metadata that can be added to Java source code. Classes, methods, variables, parameters and Java packages may be annotated. Like Javadoc tags, Java annotations can be read from source files.

What is apt in Java?

The apt tool is a command-line utility for annotation processing. It includes a set of reflective APIs and supporting infrastructure to process program annotations (JSR 175). These reflective APIs provide a build-time, source-based, read-only view of program structure.

What is annotation and why it is used in Java?

Annotations are used to provide supplemental information about a program. Annotations start with '@'. Annotations do not change the action of a compiled program. Annotations help to associate metadata (information) to the program elements i.e. instance variables, constructors, methods, classes, etc.


1 Answers

This sounds more like AOP (Aspect oriented programming) than annotations. The topics are often confused since AOP uses annotations to achieve it's goals. Rather than reinvent AOP from scratch, I would recommend looking up and existing AOP library such as AspectJ.

However, to answer your specific question, there are two possible approaches to achieve your goal.

Runtime Approach

This is the approach typically taken by container frameworks (like Spring). The way it works is that instead of instantiating your classes yourself, you ask a container for an instance of your class.

The container has logic to examine the class for any RuntimeAnnotations (like @Widgetize). The container will then dynamically create a proxy of your class that calls the correct Widgetize method first and then calls the target method.

The container will then return that proxy to the original requester. The requester will still thing he got the class (or interface) that he asked for and be completely unaware of the proxying behavior added by the container.

This is also the behavior used by AspectJ.

Enhancement Approach

This is the approach taken by AspectJ. To be honest, I don't know a lot of the details of how it works. Somehow, AspectJ will scan your class files (the byte code), figure out where the annotations are, and then modify the byte code itself to call the proxy class instead of the actual class.

The benefit of this approach is that you don't need to use a container. The drawback is that you now have to do this enhancement step after you compile your code.

like image 84
Pace Avatar answered Oct 03 '22 17:10

Pace