做一个自定义注解

一、注解是什么
  1. 注解的定义
    • 注解是一种元数据形式(元数据就是冠以数据的数据), 即注解是属于java的一种数据类型,和类、接口、数组、枚举类似。
    • 注解用来修饰,类、方法、变量、参数、包 。
    • 注解不会对所修饰的代码产生直接的影响。
        2. 注解可以干嘛,注解的基本作用
    • 生成文档
    • 代替配置文件的功能
    • 编译时进行格式检查
 
二、使用注解的好处
  • 注解与xml配置的区别
    • 注解:是一种分散式的元数据,与源代码耦合。
    • xml :是一种集中式的元数据,与源代码解耦。
  • 注解的缺点
    • 因为会分散到很多类中所以不好管理和维护
    • 如果需要更改会改变源代码
    • 缺乏灵活性
    • 缺乏可扩展性和复杂性
  • 注解的优点
    • 注解比较方便
    • 简化配置提高开发效率
    • 类型安全,xml只有在运行时才能发现问题
 
三、注解是干嘛的
  • 标准注解
    • @Override
    • @Deprecated
    • @SuppressWarnings
  • 元注解
    • @Retention(注解保留策略)
      • @Retention(RetentionPolicy.SOURCE)   // 注解仅存在于源码中,在class字节码文件中不包含
      • @Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
      • @Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
    • @Target(注解的作用目标)
      • @Target(ElementType.TYPE)                      // 接口、类、枚举、注解
      • @Target(ElementType.FIELD)                     // 字段、枚举的常量
      • @Target(ElementType.METHOD)                 // 方法
      • @Target(ElementType.PARAMETER)            // 方法参数
      • @Target(ElementType.CONSTRUCTOR)       // 构造函数
      • @Target(ElementType.LOCAL_VARIABLE)   // 局部变量
      • @Target(ElementType.ANNOTATION_TYPE) // 注解
      • @Target(ElementType.PACKAGE)               // 包
    • @Documented(注解包含在javadoc中)
    • @Inhertied(允许子类继承父类中的注解)
 
四、如何使用自定义注解
  •  定义注解
    • 定义注解用@interface 来标识 会自动继承java.lang.annotation.Annotation接口
    • 注解类型元素
      • 基本类型
      • String
      • class
      • enum
      • annotation
      • 以上类型的数组
  • 配置注解
package com.annotations;

import java.lang.annotation.Documented;
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) 作用于方法上
* @author 果咩
*/

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {

   // 描述
   String actiondese() default "";

   //类型
   public enum Logtype {ADD,UPDATE,DEL,SET,LOGIN,LOGOUT,MESSAGE};
   Logtype actionvalue() default Logtype.ADD;

}
  • 解析注解
    • <T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
    • Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
    • boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
    • Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
public class TestAnnotation {
    public static void main(String[] args){
        try {
            //获取Student的Class对象
            Class stuClass = Class.forName("pojos.Student");

            //说明一下,这里形参不能写成Integer.class,应写为int.class
                        //获取注解所标注的方法
            Method stuMethod = stuClass.getMethod("study",int.class);

            if(stuMethod.isAnnotationPresent(LogAnnotation.class)){
                System.out.println("Student类上配置了logAnnotation注解!");
                //获取该元素上指定类型的注解
                LogAnnotation logAnnotation= stuMethod.getAnnotation(LogAnnotation.class);
                                //打印
                System.out.println("actionDesc: " +logAnnotation.actiondese() + ",actionvalue: " + logAnnotation.actionvalue());
            }else{
                System.out.println("Student类上没有配置logAnnotation注解!");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

关注公众号,回复:java面试题,即可获得共几百页的java面试题

原文地址:https://www.cnblogs.com/guomie/p/10824973.html