注解详解

一:注解的作用

注解是jdk5引入的新特性,注解相当于增加了一个配置,当我们使用注解时,我们可以通过反射获取注解从而获取相关的配置,方便我们在代码层面做一些操作。

二:注解的相关概念以及使用

注解的分类:   

  • 供javadoc生成文档用的注解。@param @return 等。
  • 自定义注解,相当于配置文件的作用,使用灵活,配置简单。
  • 在编译时进行格式检查。@override检查是否重写了父类方法。@SuppressWarnings抑制编译器产生的警告信息。@Deprecated标记过时的方法等不推荐再使用。

  包 java.lang.annotation 中包含所有定义自定义注解所需用到的元注解和接口。所有注解默认继承了java.lang.annotation.Annotation接口。

注解中概念:

自定义注解时使用了四个元注解,就是用于注解的注解。四个元注解分别是:@Target,@Retention,@Documented,@Inherited。

@Target定义注解作用的地方。可以是类、方法、属性等。常用的值由一个枚举类定义:ElementType。

ElementType.FIELD,//作用在属性上
ElementType.METHOD,//作用在方法上
ElementType.CONSTRUCTOR,//作用在构造函数上
ElementType.LOCAL_VARIABLE,//作用在本地变量上
ElementType.PACKAGE,//作用在包上
ElementType.PARAMETER,//作用在方法参数上
ElementType.TYPE//作用在类,接口,枚举类等

@Retention定义了注解的生命周期,即注解在什么范围内有效。

  • SOURCE:注解仅存在于源码中,在class字节码文件中不包含
  • CLASS:默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
  • RUNTIME:注解会在class字节码文件中存在,在运行时可以通过反射获取到

@Documented 表示此注解作用的内容会被javadoc工具提取到文档中。

@Inherited表示该注解会被继承。使用该元注解的自定义注解一般作用范围是ElementType.TYPE,如果是作用在ElementType.METHOD的注解,在子类重写了使用注解的方法的时候,此时子类重载方法是没有继承该注解的,不重写方法则子类可以获取继承的注解。

自定义注解的方式:

使用@interface来定义一个自定义注解,使用方法定义自定义注解中的属性,方法的返回值定义属性值的类型。

注解使用案例一:

注解定义:   

@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DatasourceAnnotation {
    String datasourceName();
    int sequence();
}

注解使用:

public class UserService {
    @DatasourceAnnotation(datasourceName = "master", sequence = 1)
    public String datasourceName;

    @DatasourceAnnotation(datasourceName = "salve", sequence = 2)
    public String selectUserNameById(Integer id) {
        return "test";
    }
}
public class AnnotationTest {
    private void handleFieldAnnotation() throws NoSuchFieldException {
        Field datasourceName = UserService.class.getField("datasourceName");//获取属性
        if (datasourceName.isAnnotationPresent(DatasourceAnnotation.class)) {//判断属性上有无此注解
            DatasourceAnnotation annotation = datasourceName.getAnnotation(DatasourceAnnotation.class);//获取注解
            System.out.println(annotation.datasourceName());
            System.out.println(annotation.sequence());
        }
    }

    private void handleMethodAnnotation() throws NoSuchMethodException {
        Method selectUserNameById = UserService.class.getMethod("selectUserNameById", Integer.class);
        if (selectUserNameById.isAnnotationPresent(DatasourceAnnotation.class)) {
            DatasourceAnnotation annotation = selectUserNameById.getAnnotation(DatasourceAnnotation.class);
            System.out.println(annotation.datasourceName());
            System.out.println(annotation.sequence());
        }
    }


    @Test
    public void test() throws Exception {
        handleFieldAnnotation();
        handleMethodAnnotation();
    }
}

运行结果:

master
1
salve
2

Process finished with exit code 0

注解使用案例二:继承注解(作用在ElementType.METHOD上 子类的重写方法是无法继承注解的,不重写方法子类是可以获取注解的)

注解定义:

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedAnnotation {
    String name();
}

注解使用:

@InheritedAnnotation(name = "test")
public class UseInheritedAnnotation {
}
public class SubUseInheritedAnnotation extends UseInheritedAnnotation{
}
@Test
    public void test() throws Exception {
        InheritedAnnotation annotation = SubUseInheritedAnnotation.class.getAnnotation(InheritedAnnotation.class);
        System.out.println(annotation.name());
    }

运行结果:

test

Process finished with exit code 0

作用在ElementType.METHOD上 子类的重写方法是无法继承注解的,不重写方法子类是可以获取注解的

public class UseInheritedAnnotation {
    @InheritedAnnotation(name = "methodTest")
    public String test(){
        return "";
    }
}
public class SubUseInheritedAnnotation extends UseInheritedAnnotation{
    @Override
    public String test(){
        return "";
    }
}
@Test
    public void test() throws Exception {
        Method test = SubUseInheritedAnnotation.class.getMethod("test", null);
        InheritedAnnotation annotation = test.getAnnotation(InheritedAnnotation.class);
       
        System.out.println(annotation.name());
    }

运行结果:

java.lang.NullPointerException
    at com.ctj.annotationTest.AnnotationTest.test(AnnotationTest.java:35)

参考:https://blog.csdn.net/bao19901210/article/details/17201173

猜你喜欢

转载自blog.csdn.net/u011447614/article/details/83184957
今日推荐