1. 程式人生 > 實用技巧 >Java註解之獲取註解內部資料的原因分析

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

總結

之所以被註解內部能夠獲取註解內部資料根本原因就在於通過被註解物件位元組碼檔案能夠獲取到該物件位元組碼檔案中是否含有註解,並能夠通過該位元組碼檔案獲取註解內部資料,因此更簡便的實現了配置檔案相同的功能。