Annotation

在spring、hibernate等流行的开源框架中,基本上来进行配置的方式有两种,一种是基于配置文件的配置,注入applicationContext.xml或者是hbm.xml,一样另外一种方式则是基于注解的配置,能够说使用注解的配置至关的简洁明了,因此这里就再来回顾一下什么是Annotation。java

1、Annotation基本概念spring

Annotation是jdk5之后出现的新特性,在jdk中,其内置了许多本身的Annotation,例如@Override,@SuppresWarning,@Deprecated等等,其中一些Annotation是标志性的Annotation,例如@Override就是表示这个类要重写父类的方法。数组

咱们首先要清楚的知道一点,其实Annotation和Class、Interface这些同样,都是类级别的,并且咱们建立的每个Annotation都默认的继承了java.lang.annotation.Annotation这个接口,注意:若是一个接口继承了这个Annotation接口,那么这个接口并非一个Annotationapp

咱们接下来本身建立一个简单的Annotation:框架

public @interface MyAnnotation
{
    String value();
    String name() default "xiaoluo";
}

这样就定义了咱们本身的一个Annotation了,它的标识符就是  @interface,一样,Annotation里面能够定义咱们的属性,例如,上面的例子我就定义了两个String类型的属性,一个是value属性,一个是name属性,注意:在Annotation里定义属性,属性后面都要加上括号。同时咱们还能够给Annotation的属性设置默认值,经过 default 这个关键字来设置默认值,接下来咱们就可使用咱们本身定义的Annotation了:ide

@MyAnnotation(value="hello", name="world")
public class AnnotationTest
{
    @MyAnnotation("xiaoluo")
    public void hello()
    {
        System.out.println("This is my Annotation!");
    }
}

咱们看到,这个时候咱们就能够在类上面、方法上面使用咱们的Annotation了,注意:在本身定义的Annotation中,若是为其设置了属性,则咱们必需要给其属性赋值函数

在上面的例子中,咱们看到 @MyAnnotation(value="hello", name="world") 这里就是给其 value属性和name 属性赋值,而在下面的那个Annotation中:spa

@MyAnnotation("xiaoluo"),咱们没有指定其属性名,那么它是赋值给谁呢?在Annotation中,若是咱们定义了一个 value 属性,那么咱们在使用该Annotation,给其赋值时,能够不用写出属性的名字,即valuehibernate

怎么样,简单吧,这样咱们就定义并使用了咱们的Annotation了。code

2、Retention和RetentionPolicy

在初步了解了Annotation以后,咱们再来看看Retention和RetentionPolicy这两个概念,Retention的中文意思是,保留、持有,一样,Retention也是一个Annotation,经过这个注解,咱们能够指定咱们本身定义的Annotation的保留范围,其默认值是有三个,是枚举类型的值,RetentionPolicy.CLASS(这个是Retention的默认值,表示这个Annotation会被编译到class文件当中), RetentionPolicy.RESOURCE(这个表示Annotation仅仅在编译的时候有效,起到提示做用,并不会被编译到class文件当中去), RetentionPolicy.RUNTIME(这个表示Annotation不只会被编译到class文件当中,并且会在JVM运行中也能够获得这个Annotation,这样咱们就能够经过反射来获得Annotaion,并对其进行一些操做了),咱们来看看jdk自带的一些Annotation,其Retention分别是什么:

@Retention(value=SOURCE)
public @interface Override

@Retention(value=SOURCE)
public @interface SuppressWarnings

@Retention(value=RUNTIME)
public @interface Deprecated

咱们看到,Deprecated的RetentionPolicy是RUNTIME的,这样咱们能够经过反射在运行时获得其Annotation,接下来咱们本身来指定咱们刚定义的MyAnnotation为RUNTIME:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
    String value();
    String name() default "xiaoluo";
}

这个时候,咱们定义的Annotation就会被编译到class文件当中去,而且在运行时能够获得它,接下来咱们来经过一个例子来看看如何使用反射机制获得咱们的Annotation以及咱们设置的属性值,java的API指定了访问获得Annotation的方法,咱们的Class,Method,Constructor等等这些都默认实现了 AnnotatedElement 这个接口,这个接口定义了四个经常使用的方法:

<T extends Annotation> T  getAnnotation(Class<T> annotationClass)    // 根据Annotation.class获得这个Annotation

Annotation[] getAnnotations()    //  获得一个Annotation数组

Annotation[] getDeclaredAnnotations()  //  也是获得一个Annotation数组

boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)    //  判断是否为被当前的Annotation所标识
@MyAnnotation("hello")
public class AnnotationTest
{
    @MyAnnotation(value="xiaoluo", name="welcome")
    public void hello()
    {
        System.out.println("This is my Annotation!");
    }
    
    public static void main(String[] args) throws Exception
    {
        //    获得AnnotationTest这个类的 class 对象
        Class<AnnotationTest> clazz = AnnotationTest.class;
        
        //    获得AnnotationTest的一个实例对象
        AnnotationTest test = (AnnotationTest)clazz.newInstance();
        
        //    获得方法名为hello的Method对象
        Method method = clazz.getMethod("hello", new Class[]{});
    
        //    判断hello这个方法是否被MyAnnotation这个注解所标记
        if(method.isAnnotationPresent(MyAnnotation.class))
        {
            //    获得咱们的MyAnnotation这个注解
            MyAnnotation myAnnotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
            
            System.out.println(myAnnotation.name() + ", " + myAnnotation.value());
            
            method.invoke(test, new Object[]{});
        }
    }
}

咱们来看看,由于咱们的@MyAnnotation设置了其RetentionPolicy为RUNTIME,因此咱们能够在经过反射在运行时获得该Annotation对象,结果输出为:

welcome, xiaoluo
This is my Annotation!

经过这个例子,我想你们应该知道了RecentPolicy的三个值的含义了吧,咱们均可以设置其为RUNTIME,这样就能够在运行时对其进行判断来处理咱们的业务逻辑了

3、Target和ElementType

最后咱们来看看Target和ElementType这两个东东,Target这个也是一个注解,这个Annotation是用来指定咱们的Annotation能够标志的范围,例如定义在类上,定义在方法上等等,其value就是经过ElementType来指定的,咱们来看看ElementType有哪些值:

ANNOTATION_TYPE     // 能够定义在Annotation上

CONSTRUCTOR         // 能够定义在构造函数上

FIELD          // 能够定义属性上

LOCAL_VARIABLE    // 能够定义在方法的局部变量上

METHOD         // 能够定义在方法上

PACKAGE        // 能够定义在包上
  
PARAMETER       // 能够定义在方法的参数上

TYPE         // 能够定义在类上、接口上

咱们也能够在刚才定义的MyAnnotation上设置咱们的Target:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
    String value();
    String name() default "xiaoluo";
}

表示MyAnnotation能够定义在类上还有方法上,若是在其余地方定义该注解,则会编译不经过

好了,Annotation的知识基本就是这些了,主要讲解了Annotation的基本概念以及其的一些特性

相关文章
相关标签/搜索