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
复制代码

总结

之所以被注解内部能够获取注解内部数据根本原因就在于通过被注解对象字节码文件能够获取到该对象字节码文件中是否含有注解,并能够通过该字节码文件获取注解内部数据,因此更简便的实现了配置文件相同的功能。

 

posted @   佛祖让我来巡山  阅读(569)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~

佛祖让我来巡山博客站 - 创建于 2018-08-15

开发工程师个人站,内容主要是网站开发方面的技术文章,大部分来自学习或工作,部分来源于网络,希望对大家有所帮助。

Bootstrap中文网

点击右上角即可分享
微信分享提示