Saturday, December 17, 2011

Creating Your Own Annotations in Java

Annotations are java statements used for Configuration.
 Annotations are there from JSE level Like  @Deprecated,@Override
Lets look on how can we create our own annotaions


General guidelines to be followed while defining annotations:
  1. Annotation declaration should start with an ‘at’ sign like @, following with an interface keyword, following with the annotation name.
  2. Method declarations should not have any parameters.
  3. Method declarations should not have any throws clauses.
  4. Return types of the method should be one of the following:
    • primitives
    • String
    • Class
    • enum
    • array of the above types
There are specific annotations which can only be used in the context of annotations. The annotations are target, retention, documented and inherited.
Let’s look at their usage one at a time. First let’s look at target annotation. The target annotation defines which program elements can have annotations of the defined type. The user can put in the following options:
  1. TYPE: Class, interface, or enum (not annotation)
  2. FIELD: member fields (including enum values)
  3. METHOD: methods (does not include constrcutors)
  4. PARAMETER: method parameter
  5. CONSTRUCTOR: constructor
  6. LOCAL_VARIABLE: local variable or catch clause
  7. ANNOTATION_TYPE: Annotation types
  8. PACKAGE: java package
@Retention
The retention annotation indicates where and how long annotations of this type will be retained. This annotation has three options source, class and runtime. If the retention option selected is source, the annotation is discarded post compilation. Examples of such annotation types are @Override and @SuppressWarnings. The next option is class, the annotation is discarded during class load. The last option is the runtime. The annotation information marked using this option is never discarded. The annotation should be available for reflection at runtime. Example of annotation that could be useful at runtime is @Deprecated. 

@Documented
By default, the annotation and related information does not appear in the class javadoc. A marker annotation @Documented in provided to cause the annotation related information to be added in the class javadoc. The Documentation custom annotation can use the @Documented in the following manner.



Resources Needed To Create Annotations
1.An Interface(representing Annotations)
2.Client Class that uses our Annotations

3.Observer class that check whether annotations are applied on our class or not,if applied gives its behavior

Requirement
--------------
My Requirement is very simple
I will create a class with a variable,I will apply annotation to the variable with 2 arguments as number,
After the program is executed,I will get the sum of those 2 number in that variable






Sum.java
------------------------------------------------------------------------------------------------------------
package p1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sum {
    int num1() default 0;
    int num2() default 0;
}
//useage        @Sum(num1=5,num2=10)
//abstract methods of interface will act as parameter name of annotation,and return type of those methods will //act as datatype of value passed to those parameter names
---------------------------------------------------------------------------------------------------------------------------------
Container.java
------------------------------------------------------------------------------------------------------------
package p1;
import java.lang.reflect.Field;
public class Container
{
    public static void addThis(Object theObject)
    {
        try{
            Field [] fields = Class.forName(theObject.getClass().getName()).getDeclaredFields();
           
            for (int i = 0; i < fields.length; i++)
            {
                //get access to @Sum annotation
                Sum obj = fields[i].getAnnotation(Sum.class);
                if(obj != null)
                {
                    //getting values from annotations parameter
                    int val1 = obj.num1();
                    int val2 = obj.num2();
                   
                    int tot=val1+val2;
                    //setting it to our class variable
                    fields[i].setInt(theObject,tot );
                }//if
            }//for
        }catch(Exception e){e.printStackTrace();}
    }//addThis
}//class
-------------------------------------------------------------------------------------------------------------
Test.java
-------------------------------------------------------------------------------------------------------------
package p1;
public class Test
{
    @Sum(num1=15,num2=10)
    static int result;
   
    public static void main(String[] args)
    {
        Test theObject = new Test();
        Container.addThis(theObject);
        System.out.println("The Sum is "+result);
    }
}
-------------------------------------------------------------------------------------------------------------
Note:Execute Test.java and you will see Container.java injecting variables to result variable

Annotations at Method Level
------------------------------
Requirement,based on the frequency,the method will be invoked multiple times
------------------------------------------------------------------------------------------------------------------------------------
InvokeMultiple.java
--------------------------------------------------------------------------------------------------------------
package p2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface InvokeMultiple {
    int frequency() default 1;
}
--------------------------------------------------------------------------------------------------------------
MultipleInvoker.java 
--------------------------------------------------------------------------------------------------------------
package p2;

import java.lang.reflect.Method;
public class MultipleInvoker
{
    public static void invokeThis(Object theObject)
    {
        try{
            Method [] methods = Class.forName(theObject.getClass().getName()).getMethods();
            for (int i = 0; i < methods.length; i++)
            {
                InvokeMultiple invokeMultiple = methods[i].getAnnotation(InvokeMultiple.class);
                if(invokeMultiple != null)
                {
                    int count = invokeMultiple.frequency();
                    for (int j = 0; j < count; j++)
                        methods[i].invoke(theObject, null);
                }//if
            }//for
        }catch(Exception e){}
    }//invokeThis
}//class

--------------------------------------------------------------------------------------------------------------

TestObject.java
--------------------------------------------------------------------------------------------------------------
package p2;
public class TestObject
{
String name="Raja";
    @InvokeMultiple(frequency=2)
    public void printName(){
        System.out.println(name);
    }

    public static void main(String[] args) {
        TestObject theObject = new TestObject();
        MultipleInvoker.invokeThis(theObject);
    }
}
---------------------------------------------------------------------------------------------------------------

No comments:

Post a Comment