Java 自定义注解 @interface 笔记

前言

使用自定义注解,反射知识

一、了解一下基础

1、元注解(meta-annotation):
     元注解可用于自定义注解。Java定义的元注解:
    1).@Target //定义该注解可以使用在什么元素上,如类,接口等 
    2).@Retention //定义该注解的生命周期,
    3).@Documented //是一个标记注解,如可标记在javadoc
    4).@Inherited //是一个标记注解,阐述了某个被标注的类型是被继承的,如标记是否是class的子类

/** 元素类型 */
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration 声明为类、接口(包括注释类型)或枚举 */
    TYPE,
    /** Field declaration (includes enum constants)声明为字段(包括枚举常量) */
    FIELD,
    /** Method declaration 声明为方法 */
    METHOD,
    /** Formal parameter declaration 声明为正式的参数*/
    PARAMETER,
    /** Constructor declaration 声明为构造函数 */
    CONSTRUCTOR,
    /** Local variable declaration 声明为 */
    LOCAL_VARIABLE,
    /** Annotation type declaration 声明为注释类型 */
    ANNOTATION_TYPE,
    /** Package declaration 声明为包*/
    PACKAGE,
    /**
     * Type parameter declaration 声明为类型参数
     * @since 1.8
     */
    TYPE_PARAMETER,
    /**
     * Use of a type 类型的使用
     * @since 1.8
     */
    TYPE_USE
}
/** 生命周期的策略*/
public enum RetentionPolicy {
    /** Annotations are to be discarded by the compiler.只在源文件保留,其它将被编译器丢弃 */
    SOURCE,
    /** Annotations are to be recorded in the class file by the compiler
     *  but need not be retained by the VM at run time.  This is the default
     *  behavior.注释将被记录在编译器的类文件但不需要保留的虚拟机在运行时 */
    CLASS,
    /** 将由编译器记录在类文件中,并在运行时由VM保留,因此可以对它们进行反思读取
     *  Annotations are to be recorded in the class file by the compiler and
     *  retained by the VM at run time, so they may be read reflectively.
     * @see java.lang.reflect.AnnotatedElement */
    RUNTIME
}

2、自定义注解
    1).定义注解格式:
      public @interface 注解名 {定义体}
  2).注解参数的可支持数据类型:
    1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
    2.String类型
    3.Class类型
    4.enum类型
    5.Annotation类型
    6.以上所有类型的数组
    3).Annotation类型里面的参数设定格式
       类型 名称 [default 默认值]

二、自己动手_例子
1、自定义注解类

package com.myannotations;

import java.lang.annotation.*;

/**
 * 自定义一个注解为PsAnnotation类
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD})
@Documented
//@Inherited
public @interface PsAnnotation {

    String name() default "";

    String attribute();

    int num () default 0;

    String[] pids();
}

2、使用注解的实体类

package com.myannotations;

/**
 * 实体类
 */
@PsAnnotation(name = "psEntity", attribute ="pg" , pids ={"菜","刀"} )
public class PsEntity {

    @PsAnnotation(name = "id",attribute = "1111", pids = {"sc"} )
    public String id;


    public String id2;
}

3、测试类

package com.myannotations;

import com.sun.deploy.util.StringUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;

/**
 * @PsAnnotation 自定义注解
 * 测试类
 */
public class AnnotationText {

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //扫描某个包下的所有class 获取所有有注解的class ,属性
                    String packageName = "com.myannotations";
                    String packageDirName = packageName.replace('.', '/');
                    List<Class<?>> clazzs = new ArrayList<>();//所有的class
                    Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
                    while (urls != null && urls.hasMoreElements()) {
                        URL url = urls.nextElement();
                        //获取协议
                        String protocol = url.getProtocol();
                        if ("file".equals(protocol)) {
                            // 获取包的物理路径
                            String packagePath = URLDecoder.decode(url.getFile(), "UTF-8");
                            // 以文件的方式扫描整个包下的文件 并添加到集合中
                            findClassesInPackageByFile(packageName, packagePath, clazzs);
                        } else if ("jar".equals(protocol)) {
                            //todo
                        }
                    }
                    Map<String, Map<Method, Object>> methodInAnnotationMap = new HashMap<>();
                    Map<String, Class<?>> clazzInAnnotationMap = new HashMap<>();
                    Map<String, Map<Field, Object>> fieldInAnnotationMap = new HashMap<>();
                    for (Class<?> clazz : clazzs) {// 循环获取所有的类

                        if (clazz.getAnnotation(PsAnnotation.class) != null) {
                            clazzInAnnotationMap.put(clazz.getName(), clazz);
                        }
                        //获取所有属性
                        Field[] fields = clazz.getDeclaredFields();
                        Map<Field, Object> fieldObjectMap = new HashMap<>();
                        for (Field field : fields) {
                            field.setAccessible(true);
                            // 获取注解
                            Object annotation = field.getAnnotation(PsAnnotation.class);
                            if (annotation != null) {
                                fieldObjectMap.put(field, annotation);
                            }
                            if (fieldObjectMap.size() > 0)
                                fieldInAnnotationMap.put(clazz.getName(), fieldObjectMap);
                        }
                        // 获取类的所有方法
                        Method[] methods = clazz.getMethods();
                        Map<Method, Object> methodObjectMap = new HashMap<>();
                        for (Method method : methods) {
                            // 获取注解
                            Object annotation = method.getAnnotation(PsAnnotation.class);
                            if (annotation != null) {
                                methodObjectMap.put(method, annotation);
                            }
                        }
                        if (methodObjectMap.size() > 0)
                            methodInAnnotationMap.put(clazz.getName(), methodObjectMap);
                    }
                    for (Map.Entry<String, Class<?>> entry : clazzInAnnotationMap.entrySet()) {
                        PsAnnotation psAnnotation = entry.getValue().getAnnotation(PsAnnotation.class);
                        System.out.println("含有自定义注解的class :Key = " + entry.getKey() + ", psAnnotation = [" + psAnnotation.name().concat(",").concat(psAnnotation.attribute()));
                    }
                    System.out.println("===================================================================================================");
                    for (Map.Entry<String, Map<Field, Object>> entry : fieldInAnnotationMap.entrySet()) {
                        System.out.println("含有自定义注解的属性 :类 = " + entry.getKey());
                        for (Map.Entry<Field, Object> entry2 : entry.getValue().entrySet()) {
                            PsAnnotation psAnnotation = (PsAnnotation) entry2.getValue();
                            System.out.println("含有自定义注解的属性 : 属性 = " + entry2.getKey() + ", psAnnotation = [" + psAnnotation.name().concat(",").concat(psAnnotation.attribute()));
                        }
                    }
                    System.out.println("===================================================================================================");
                    for (Map.Entry<String, Map<Method, Object>> entry : methodInAnnotationMap.entrySet()) {
                        System.out.println("含有自定义注解的方法 :类 = " + entry.getKey());
                        for (Map.Entry<Method, Object> entry2 : entry.getValue().entrySet()) {
                            PsAnnotation psAnnotation = (PsAnnotation) entry2.getValue();
                            System.out.println("含有自定义注解的方法 : 方法 = " + entry2.getKey() + ", psAnnotation = [" + psAnnotation.name().concat(",").concat(psAnnotation.attribute()));
                        }
                    }
                    System.out.println("======================end===========================================================================");
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

        }).start();
    }

    public static void findClassesInPackageByFile(String packageName, String packagePath, List<Class<?>> clazzs) throws Exception {
        // 获取此包的目录 建立一个File
        File dir = new File(packagePath);
        // 如果不存在或者 直接返回
        if (!dir.exists()) {
            return;
        }
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            for (File file : files) {
                // 如果是目录 则继续扫描
                if (file.isDirectory())
                    findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), clazzs);
                else if (file.getName().endsWith(".class")) {
                    String className = file.getName().substring(0, file.getName().length() - 6);
                    clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
                }
            }
        } else if (dir.getName().endsWith(".class")) {
//            String name = dir.getPath();
            String className = dir.getName().substring(0, dir.getName().length() - 6);
            // 添加到集合中去
            clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值