• Java注解之获取注解内部数据的原因分析


    我们都知道从JDK1.5开始,注解开始被支持使用,当我们在使用注解的时候感觉比配置文件用起来更加简便和清爽。配置文件是通过解析配置文件的内容获取到数据,那么为什么仅仅在类、方法或者属性上添加注解被注解对象就内部就能获取到注解内部的数据了呢?

    一、给类添加单个注解

    1、自定义一个注解:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Classname Pro
     * @Description TODO
     * @Date 2020/9/16 17:27
     * @Created by Administrator
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Pro {
        String className();
        String methodName();
    }
    View Code

    2、定义一个类用于测试类通过反射创建对象调用其内部方法

    /**
     * @Classname User
     * @Description TODO
     * @Date 2020/9/16 17:28
     * @Created by Administrator
     */
    public class User {
        public void eat(){
            System.out.println("吃饭...");
        }
    
        public void drink(){
            System.out.println("喝水...");
        }
    }
    View Code

    3、定义一个测试类用于测试注解内数据是如何被获取到的

    import java.lang.reflect.Method;
    
    /**
     * @Classname AnnotationClassTest
     * @Description TODO
     * @Date 2020/9/16 17:29
     * @Created by Administrator
     */
    @Pro(className = "User",methodName = "eat")
    public class AnnotationClassTest {
        public static void main(String[] args) throws Exception {
            // 1 获取被注解位置的字节码对象
            Class<AnnotationClassTest> testClass = AnnotationClassTest.class;
            // 2 根据注解的字节码对象创建注解对象
            Pro annotation = testClass.getAnnotation(Pro.class);
            // 3 根据注解对象获取注解内部数据
            String className = annotation.className();
            String methodName = annotation.methodName();
            // 3.1打印获取到的注解数据
            System.out.println(className);
            System.out.println(methodName);
            // 4 通过反射通过获取到的className获取该类字节码对象
            Class aClass = Class.forName(className);
            // 5 通过该字节码对象根据获取到的methodName获取方法对象
            Method method = aClass.getMethod(methodName);
            // 6 通过类字节码对象生成该类对象
            User user= (User) aClass.newInstance();
            // 7 方法执行
            method.invoke(user);
        }
    }
    View Code

    二、给方法添加单个注解

    1、自定义一个注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Classname Pro
     * @Description TODO
     * @Date 2020/9/16 17:27
     * @Created by Administrator
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Pro2 {
        String className();
        String methodName();
    }
    View Code

    2、定义一个类用于测试类通过反射创建对象调用其内部方法

    /**
     * @Classname User
     * @Description TODO
     * @Date 2020/9/16 17:28
     * @Created by Administrator
     */
    public class User {
        public void eat(){
            System.out.println("吃饭...");
        }
    
        public void drink(){
            System.out.println("喝水...");
        }
    }
    View Code

    3、定义一个测试类用于测试注解内数据是如何被获取到的

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    /**
     * @Classname AnnotationClassTest
     * @Description TODO
     * @Date 2020/9/16 17:29
     * @Created by Administrator
     */
    
    public class AnnotationMethodTest {
        @Pro2(className = "User",methodName = "eat")
        public static void main(String[] args) throws Exception {
            // 1 获取被注解位置的字节码对象
            Class<AnnotationMethodTest> testClass = AnnotationMethodTest.class;
            // 2 根据注解的字节码对象创建注解对象
            Pro2 annotation = testClass.getMethod("main", String[].class).getAnnotation(Pro2.class);
            // 3 根据注解对象获取注解内部数据
            String className = annotation.className();
            String methodName = annotation.methodName();
            // 4 通过反射通过获取到的className获取该类字节码对象
            Class aClass = Class.forName(className);
            // 5 通过该字节码对象根据获取到的methodName获取方法对象
            Method method = aClass.getMethod(methodName);
            // 6 通过类字节码对象生成该类对象
            User user= (User) aClass.newInstance();
            // 7 方法执行
            method.invoke(user);
        }
    }
    View Code

    三、给类添加多个注解

    1、自定义两个注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Classname Pro
     * @Description TODO
     * @Date 2020/9/16 17:27
     * @Created by Administrator
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Pro {
        String className();
        String methodName();
    }
    自定义注解1
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Classname Pro
     * @Description TODO
     * @Date 2020/9/16 17:27
     * @Created by Administrator
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Pro3 {
        String className();
        String methodName();
        String age();
    }
    自定义注解2

    2、定义一个类用于测试类通过反射创建对象调用其内部方法

    /**
     * @Classname User
     * @Description TODO
     * @Date 2020/9/16 17:28
     * @Created by Administrator
     */
    public class User {
        public void eat(){
            System.out.println("吃饭...");
        }
    
        public void drink(){
            System.out.println("喝水...");
        }
    }
    View Code

    3、定义一个测试类用于测试注解内数据是如何被获取到的

    import java.lang.reflect.Method;
    
    /**
     * @Classname AnnotationClassTest
     * @Description TODO
     * @Date 2020/9/16 17:29
     * @Created by Administrator
     */
    @Pro(className = "User",methodName = "eat")
    @Pro3(className = "User",methodName = "drink",age = "23")
    public class AnnotationClassTest2 {
        public static void main(String[] args) throws Exception {
            // 1 获取被注解位置的字节码对象
            Class<AnnotationClassTest2> testClass = AnnotationClassTest2.class;
            Pro annotation = testClass.getAnnotation(Pro.class);
            String className = annotation.className();
            String methodName = annotation.methodName();
            Class aClass = Class.forName(className);
            Method method = aClass.getMethod(methodName);
            User user= (User) aClass.newInstance();
            method.invoke(user);
    
            Pro3 annotation2 = testClass.getAnnotation(Pro3.class);
            String className2 = annotation2.className();
            String methodName2 = annotation2.methodName();
            Class aClass2 = Class.forName(className2);
            Method method2 = aClass2.getMethod(methodName2);
            User user2= (User) aClass2.newInstance();
            method2.invoke(user2);
        }
    }
    View Code

    总结

    之所以被注解内部能够获取注解内部数据根本原因就在于通过被注解对象字节码文件能够获取到该对象字节码文件中是否含有注解,并能够通过该字节码文件获取注解内部数据,因此更简便的实现了配置文件相同的功能。
  • 相关阅读:
    递归函数
    Java以缓冲字符流向文件写入内容(如果文件存在则删除,否则先创建后写入)
    Python将文本内容读取分词并绘制词云图
    查询数据库数据并传入servlet
    向数据库添加记录(若有则不添加)
    2月16日学习记录
    2月15日学习记录
    2月14日学习记录
    Echart学习
    JavaScript深入学习(六)Ajax技术
  • 原文地址:https://www.cnblogs.com/sun-10387834/p/13683436.html
Copyright © 2020-2023  润新知