• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

无信不立

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【spring微服务】spring-boot之注解回顾

一、元注解

元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它的注解上面。

@Retention、@Documented、@Target、@Inherited、@Repeatable 5 种

1、 @Retention

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

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

2、@Documented

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

 

3、@Target

Target 是目标的意思,@Target 指定了注解运用的地方。

你可以这样理解,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。

  • ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
  • ElementType.CONSTRUCTOR 可以给构造方法进行注解
  • ElementType.FIELD 可以给属性进行注解
  • ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
  • ElementType.METHOD 可以给方法进行注解
  • ElementType.PACKAGE 可以给一个包进行注解
  • ElementType.PARAMETER 可以给一个方法内的参数进行注解
  • ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

4、@Inherited

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

两个注解例子

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Getter {
    String sex() default "";
}





import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Setter {
    String name() default "";

    int length() default 0;

}
View Code

子类和父类

@Setter(name = "java",length = 30)
public class Parent {
}


@Getter(sex = "男")
public class Son extends Parent{

}
View Code

测试例子

public class Test {
    /**
     *注解属性[名字]=java
     * 注解属性[长度]=30
     * 注解属性[长度]=30
     * 注解属性[名字]=java
     * 注解属性[性别]=男
     * @param args
     */
    public static void main(String[] args) {
        Class<Son> cls=Son.class;
        //获取类上的所有注解
        Annotation[] annotations=cls.getAnnotations();
        //获取类上的指定注解
        Setter setter= cls.getAnnotation(Setter.class);
        System.out.println("注解属性[名字]="+setter.name());
        System.out.println("注解属性[长度]="+setter.length());
        //遍历所有注解
        for(Annotation annotation:annotations){
            Class c=annotation.annotationType();
            if(c.isAssignableFrom(Setter.class)){
                Setter set= (Setter) annotation;
                System.out.println("注解属性[长度]="+set.length());
                System.out.println("注解属性[名字]="+set.name());
            }
            if(c.isAssignableFrom(Getter.class)){
                Getter get= (Getter) annotation;
                System.out.println("注解属性[性别]="+get.sex());
            }
        }
    }
}
View Code

如果子类和父类使用相同的注解,则子类会覆盖父类的注解

子类和父类

@Setter(name = "java",length = 30)
public class Parent {
}

@Setter(name = "c",length = 12)
public class Son extends Parent{

}
View Code

测试例子

public class Test {
    /**
     * 注解属性[名字]=c
     * 注解属性[长度]=12
     * 注解属性[长度]=12
     * 注解属性[名字]=c
     * @param args
     */
    public static void main(String[] args) {
        Class<Son> cls=Son.class;
        //获取类上的所有注解
        Annotation[] annotations=cls.getAnnotations();
        //获取类上的指定注解
        Setter setter= cls.getAnnotation(Setter.class);
        System.out.println("注解属性[名字]="+setter.name());
        System.out.println("注解属性[长度]="+setter.length());
        //遍历所有注解
        for(Annotation annotation:annotations){
            Class c=annotation.annotationType();
            if(c.isAssignableFrom(Setter.class)){
                Setter set= (Setter) annotation;
                System.out.println("注解属性[长度]="+set.length());
                System.out.println("注解属性[名字]="+set.name());
            }
            if(c.isAssignableFrom(Getter.class)){
                Getter get= (Getter) annotation;
                System.out.println("注解属性[性别]="+get.sex());
            }
        }
    }
}
View Code

 

5、@Repeatable

Repeatable 自然是可重复的意思。@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。

什么样的注解会多次应用呢?通常是注解的值可以同时取多个。

举个例子,一个人他既是程序员又是产品经理,同时他还是个画家。

@interface Persons {
    Person[]  value();
}


@Repeatable(Persons.class)
@interface Person{
    String role default "";
}


@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{

}
View Code

注意上面的代码,@Repeatable 注解了 Person。而 @Repeatable 后面括号中的类相当于一个容器注解。

什么是容器注解呢?就是用来存放其它注解的地方。它本身也是一个注解。

我们再看看代码中的相关容器注解。

@interface Persons {
    Person[]  value();
}
View Code

按照规定,它里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解过的注解数组,注意它是数组。

如果不好理解的话,可以这样理解。Persons 是一张总的标签,上面贴满了 Person 这种同类型但内容不一样的标签。把 Persons 给一个 SuperMan 贴上,相当于同时给他贴了程序员、产品经理、画家的标签。

我们可能对于 @Person(role=”PM”) 括号里面的内容感兴趣,它其实就是给 Person 这个注解的 role 属性赋值为 PM ,大家不明白正常,马上就讲到注解的属性这一块。

 

二、注解的属性

注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Setter {
    String name() default "";

    int length() default 0;

}
View Code

 

三、注解提取

1、注解与反射

注解通过反射获取。首先可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
View Code

然后通过 getAnnotation() 方法来获取 Annotation 对象。

public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
View Code

或者是 getAnnotations() 方法。

public Annotation[] getAnnotations() {}
View Code

 

 

四、组合注解

1、一个组合注解的例子

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
public @interface Config {
    String pathVaule() default "组合注解";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
@Config
public @interface Company {

    String path() default "";
}


@Company(path = "sd")
public class NameClass {
}
View Code

2、解析组合注解

sd
组合注解
注解详情:interface java.lang.annotation.Retention
注解详情:interface java.lang.annotation.Target
注解详情:interface java.lang.annotation.Inherited
注解详情:interface java.lang.annotation.Documented
注解详情:interface com.spring.test.service.javacore.annotation.Config


public static void test02() {
//spring提供的AnnotationUtils工具类
        Config config= AnnotationUtils.findAnnotation(NameClass.class,Config.class);
        Company company=AnnotationUtils.findAnnotation(NameClass.class,Company.class);
        System.out.println(company.path());
        System.out.println(config.pathVaule());
        Annotation[] annotations=NameClass.class.getDeclaredAnnotations();
        for(Annotation annotation:annotations){
            Annotation[] annotations1= annotation.annotationType().getAnnotations();
            for(Annotation a:annotations1){
                System.out.println("注解详情:"+a.annotationType());
            }
        }
    }
View Code

 

posted on 2019-09-25 11:01  无信不立  阅读(212)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3