總說自定義註解,可是自定義註解到底該怎麼用?

您的關注是我最大的動力

隨着軟件開發的發展,xml配置已經被註解所取代,註解被越來越多的運用到我們的代碼中了。如果我們想要使自己定義的註解來進行一些操作該怎麼做呢?

自定義註解

在項目中新建Java文件是選擇Annotation類型則會爲我們創建一個註解文件。關於註解的詳細介紹可以看之前寫的註解詳解文章。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Scope("prototype")
public @interface XyhBean {
}

上面創建的這個註解表名這是一個在運行時起作用的註解,並且只能作用於類上,而且作用的類不是一個單例。

使用場景

在我們的項目中可能會遇到這樣的情況,需要一個工廠或者Map來存儲一些類的信息,在之後的使用過程中通過工廠或者Map來獲取到我們所需要的類。在一般情況下我們可能就會使用Map來進行這個操作。但是每當項目中新增一個類就要往Map中也操作一次,這樣會非常的麻煩並且容易出現問題,因此我們使用自定義註解通過spring來幫我們操作。

ApplicationListener

在一些業務場景中,當容器初始化完成之後,需要處理一些操作,比如一些數據的加載、初始化緩存、特定任務的註冊等等。這個時候我們就可以使用Spring提供的ApplicationListener來進行操作。

@Component
public class ContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
    public static Map<String, Object> beanMap = new HashMap<>();

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        beanMap = event.getApplicationContext().getBeansWithAnnotation(XyhBean.class);
    }
}

項目啓動之後,讀取所有註解了XyhBean註解的類放進我們事先定義好的Map中。

通過反射處理註解

上面的方法是通過Spring來幫助我們實現了一個簡單的自定義註解場景,如果有更加複雜的場景的話就需要藉助Java的反射來完成了。

註解處理器類庫(java.lang.reflect.AnnotatedElement):

Java使用Annotation接口來代表程序元素前面的註解,該接口是所有Annotation類型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,該接口代表程序中可以接受註解的程序元素,該接口主要有如下幾個實現類:

  • Class:類定義
  • Constructor:構造器定義
  • Field:累的成員變量定義
  • Method:類的方法定義
  • Package:類的包定義

java.lang.reflect 包下主要包含一些實現反射功能的工具類,實際上,java.lang.reflect 包所有提供的反射API擴充了讀取運行時Annotation信息的能力。當一個Annotation類型被定義爲運行時的Annotation後,該註解才能是運行時可見,當class文件被裝載時被保存在class文件中的Annotation纔會被虛擬機讀取。

AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通過反射獲取了某個類的AnnotatedElement對象之後,程序就可以調用該對象的如下四個個方法來訪問Annotation信息:
方法1. <T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回該程序元素上存在的、指定類型的註解,如果該類型註解不存在,則返回null。
方法2. Annotation[] getAnnotations():返回該程序元素上存在的所有註解。
方法3. boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判斷該程序元素上是否包含指定類型的註解,存在則返回true,否則返回false.
方法4:Annotation[] getDeclaredAnnotations():返回直接存在於此元素上的所有註釋。與此接口中的其他方法不同,該方法將忽略繼承的註釋。(如果沒有註釋直接存在於此元素上,則返回長度爲零的一個數組。)該方法的調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響。

public class AnnotationUtil {
    public static boolean getFruitInfo(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(XyhBean.class)) {
                return true;
            }
        }
        return false;
    }
}

以上代碼可以用來判斷傳進來的類是否註解了我們自己定義的註解。具體使用的方法需要根據使用場景來進行選擇。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章