1. 程式人生 > >深入淺出 java 註解-06-java 動態設定註解的屬性

深入淺出 java 註解-06-java 動態設定註解的屬性

目錄

設定註解的屬性

這種使用場景比較少,但是不失為一種對於註解的深入理解。

例項

定義

  • Tag.java
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.TYPE, ElementType.METHOD, ElementType.LOCAL_VARIABLE}) public @interface Tag { /** * tag 標籤 * * @return tag */ String value() default ""; }

使用

  • SetValue.java

設定註解的屬性

import com.ryo.jdk.annotation.define.Tag;

import org.junit.Assert;

import java.lang.reflect.Field;
import
java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Map; public class SetValue { /** * 在每一個類執行之前,設定註解的屬性 * @throws NoSuchFieldException if any * @throws IllegalAccessException if any */ @SuppressWarnings("unchecked"
) public static void beforeClass() throws NoSuchFieldException, IllegalAccessException { Method[] methods = SetValue.class.getDeclaredMethods(); for(Method method : methods) { Tag tag = method.getAnnotation(Tag.class); if(tag != null) { InvocationHandler h = Proxy.getInvocationHandler(tag); Field hField = h.getClass().getDeclaredField("memberValues"); hField.setAccessible(true); Map memberMethods = (Map) hField.get(h); memberMethods.put("value", "setAnnotation"); String value = tag.value(); Assert.assertEquals("setAnnotation", value); } } } @Tag public void tag() { } public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { beforeClass(); } }

個人遇到的使用場景

場景匯入

TestNG 中的 @DataProvider 註解,擁有 dataProvider() 屬性用來指定資料來源。

編寫的框架中 dataProvider() 值可以指向固定的值,但是 TestNG 會通過這個屬性來進行值的注入和執行。

  • @DataProvider 的屬性

編寫的框架通過註解去解析對應的配置檔案,導致所有的 @DataProvider 的 dataProvider() 可以使固定的。

但是 TestNG 通過判斷 dataProvider() 是否有值,來進行引數化測試。

所以,這是一個固定的屬性值,使用同一的屬性設定,可以使得使用者程式碼變得更加優雅。

例項

  • TestNgDataProviderTest.java
import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

public class TestNgDataProviderTest {

    /**
     * 是否為空資料準備
     * @return 資料
     */
    @DataProvider(name = "TestDataProvider")
    public Object[][] isEmptyDataProvider(Method method, ITestContext testContext) {
        return new Object[][]{
                {"", true},
                {null, true},
                {"    ", true},
                {"1", false},
                {"   1", false}
        };
    }

    /**
     * 在每一個類執行之前,設定註解的屬性
     * @throws NoSuchFieldException if any
     * @throws IllegalAccessException if any
     */
    @BeforeClass
    public void beforeClass() throws NoSuchFieldException, IllegalAccessException {
        Method[] methods = this.getClass().getDeclaredMethods();
        for(Method method : methods) {
            Test test = method.getAnnotation(Test.class);
            if(test != null) {
                InvocationHandler h = Proxy.getInvocationHandler(test);
                Field hField = h.getClass().getDeclaredField("memberValues");
                hField.setAccessible(true);
                Map memberMethods = (Map) hField.get(h);
                memberMethods.put("dataProvider", "TestDataProvider");
                String value = test.dataProvider();
                Assert.assertEquals("TestDataProvider", value);
            }
        }
    }

    @Test
    public void isEmptyTest(final String string, boolean result) {
        System.out.println(string+","+result);
        Assert.assertEquals(result, StringUtil.isEmpty(string));
    }
}

程式碼地址

引用

系列導航

系列導航