Java 自定义注解的使用

最近在做关于Redis缓存相关的东西,涉及到刷新缓存的问题,我用了注解加AOP实现的缓存的刷新,这样的话只要在增删改的时候加一个注解就可以实现对缓存的刷新.发现自己对注解和String 中的AOP的东西不是太了解,现在就对这些做一些总结和再次学习.

注解

一.定义

.Java中的注解在官方的文档中的解释

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。


个人理解是注解是一个标签,看到了这个的注解你就知道这是干什么了.比如你一看到@Override你就知道这个方法是方法的重写

...当然我们可以自定义自己用来是实现自己特定的是功能.自定义注解我个人感觉就是比较好用的,用了注解可以少很多重复代码,列如使用AOP加注解可以省的代码量太大了.要想定义自定义注解必须先要了解元注解.

二.元注解

定义:元注解就是可以加在注解上的注解.在我们定义注解的时候,需要用到这些注解在我们自定义注解的时候我们会对这些注解详细的说明.这里只需要明白它的意思就够了.

三.自定义注解

自定义注解和定义类接口差不多只不过用的关键之不一样,注解用的是@interface关键字如

public @interface Demo {
}

这样就定义了一个注解了

光是这样还不够我们需要制定这个注解的一些属性这就需要用到元注解了

用到的元注解有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 种

下面我们将详细介绍这些元注解了

1.Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。

它的取值如下: 
- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。 
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

我们可以这样的方式来加深理解,@Retention 去指定了这个注解的起作用的时间。@Retention 相当于给这个注解上面加了一个时间戳,时间戳指明了这个注解的时间周期。

代码如下

@Retention(RetentionPolicy.CLASS)
public @interface Demo12 {
}

2.Documented,这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。

代码省略

3.Target的英文意思是目标的意识.@Target加在注解上就指定了这个注解的使用位置.@Target注解里面是一个数组可以指定多个

它的取值如下

  • ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
  • ElementType.CONSTRUCTOR 可以给构造方法进行注解
  • ElementType.FIELD 可以给属性进行注解
  • ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
  • ElementType.METHOD 可以给方法进行注解
  • ElementType.PACKAGE 可以给一个包进行注解
  • ElementType.PARAMETER 可以给一个方法内的参数进行注解
  • ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
  • ElemenType.TYPE_PARAMETER 类型参数声明 1.8
  • ElemanType.TYPE_USER 类型的使用 1.8
代码如下
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)//指定一个
public @interface Demo12 {
}
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE})//指定多个
public @interface Demo12 {
}

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Demo12 {
}

4.Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。 

代码如下

//注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface Demo {
}
@Demo//注解父类
public class A {
}
//B继承与A
public class B extends A{
}
public class Test {
    public static void main(String[] args) {
           
        //获取B的class对象
        Class<B> bClass = B.class;
        //获取B类上的Demo注解可以执行成功
        Demo annotation = bClass.getAnnotation(Demo.class);

    }
}

5.Repeatable的英文意思是重复,@Repeatable是java1.8的新特性 ,这个注解在一个位置可以多次使用但是,每个注解代表的意思可能不一样.

代码如下


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Demos {
    public Demo[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Repeatable(Demos.class)
public @interface Demo {
    public String value();
}
@Demo("demo1")
@Demo("demo2")
@Demo("demo3")
public class Test {
}

这里的Demo注解就有了不同的属性在Test上就可以解析区分这些注解来加if判断做特特定的事了.

四.注解的属性

注解的属性也叫成员变量,不过它与对象的成员属性还不太一样.注解只有属性没有方法

注解的属性的定义方式为,类型 +上引用名 + ()例如 String id();如果有默认值的话可以在()后面加上default 然后加上你默认的值,当你的引用名是value且只有这一个属性的时候,这时你在使用的注解就不需要编写引用名了.当成员变量没有设置默认值时,那么在用此属性的时候就要给此属性赋值

代码如下

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Repeatable(Demos.class)
public @interface Demo {

    /**
     *引用名value,因为没有设默认值所以在用注解的时候是必填字段,如果此注解
     * 只有这一个属性此时引用名可以省略
     */
    String value();
    /**
     *引用名为id因为有默认值所以在使用时可以不用给此属性赋值
     */
    String id() default "";

}

以上就是自定义注解了,JDK,默认提供了一些注解在这里就不做介绍了.

五.注解的获取

注解的获取可以利用反射来获取利用反射的技术注意这是要记得注解的是@Retention 是Runtime

具体代码如下

public class Test {
    public static void main(String[] args) {

        //获取B的class对象
        Class<B> bClass = B.class;
        //获取B类上的特定类型的注解如果不存在的话返回为null包括继承的注解
        Demo annotation = bClass.getAnnotation(Demo.class);
        //获取类上的所有的注解包括继承的注解
        Annotation[] annotations = bClass.getAnnotations();
        //也是获取注解但不包括继承的
        bClass.getDeclaredAnnotation(Demo.class);
        //也是获取注解但不包括继承的
        Annotation[] declaredAnnotations = bClass.getDeclaredAnnotations();
        
    }
}





猜你喜欢

转载自blog.csdn.net/mypersonalsong/article/details/79582354