创建自己的Java批注
如果您一直在用Java編程并且使用諸如Spring和Hibernate之類的任何流行框架,那么您應該對使用注釋非常熟悉。 當使用現有框架時,其注釋通常就足夠了。 但是,您是否發現需要創建自己的注釋?
不久之前,我找到了一個理由來為一個項目創建自己的注釋,該注釋涉及驗證存儲在多個數據庫中的公共數據。
場景
該企業有多個存儲相同信息的數據庫,并且具有使數據保持最新狀態的各種方法。 該企業已經計劃了一個將數據整合到主數據庫中的項目,以減輕與擁有多個數據源有關的一些問題。
但是,在項目開始之前,業務部門需要了解數據之間的不同步程度,并進行必要的更正以恢復同步。 第一步需要創建一個報告,該報告顯示屬于多個數據庫的公共數據并驗證值,并根據定義的對帳規則突出顯示所有不匹配的記錄。 這是當時需求的簡短摘要:
- 比較多個數據庫之間的數據以獲取一條公共數據,例如客戶,公司或目錄信息。
- 默認情況下,根據值的類型,找到的值應與所有數據庫完全匹配。
- 對于某些字段,我們只希望顯示找到的值,而不執行任何數據比較。
- 對于某些字段,我們只想比較找到的值并在指定的特定數據源上執行數據驗證。
- 對于某些字段,我們可能希望根據記錄中其他字段的值進行一些復雜的數據比較。
- 對于某些字段,我們可能希望將數據格式化為特定格式,例如,金額為$ 000,000.00。
- 該報告應采用MS Excel格式,每行應包含來自每個來源的字段值。 根據數據驗證規則不匹配的任何行應以黃色突出顯示。
注解
在研究了需求并提出了一些想法之后,我決定使用批注來驅動數據比較和報告過程的配置。 我們需要一些簡單但又高度靈活和可擴展的東西。 這些注釋將在字段級別,我喜歡這樣的事實,即不會將配置隱藏在類路徑上的某個文件中。 相反,您將能夠查看與字段相關聯的注釋,以確切地知道將如何處理它。
用最簡單的術語來說,注釋不過是標記,即提供信息但對代碼本身的操作沒有直接影響的元數據。 如果您已經從事Java編程已有一段時間,那么您應該對它們的使用非常熟悉,但是也許您根本不需要創建自己的Java編程。 為此,您需要創建一個使用Java類型@interface的新類型,該類型將包含指定元數據詳細信息的元素。
這是該項目的一個示例:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ReconField {/*** Value indicates whether or not the values from the specified sources should be compared or will be used to display values or reference within a rule.** @return The value if sources should be compared, defaults to true.*/boolean compareSources() default true;/*** Value indicates the format that should be used to display the value in the report.** @return The format specified, defaulting to native.*/ReconDisplayFormat displayFormat() default ReconDisplayFormat.NATIVE;/*** Value indicates the ID value of the field used for matching source values up to the field.** @return The ID of the field.*/String id();/*** Value indicates the label that should be displayed in the report for the field.** @return The label value specified, defaults to an empty string.*/String label() default "";/*** Value that indicates the sources that should be compared for differences.** @return The list of sources for comparison.*/ReconSource[] sourcesToCompare() default {};}這是將驅動數據比較過程如何工作的主要注釋。 它包含滿足大多數要求以在不同數據源之間比較數據的基本要素。 @ReconField應該處理我們所需的大部分內容,除了需要進行更復雜的數據比較之外,我們將在稍后進行介紹。 這些元素中的大多數由代碼清單中與每個元素相關的注釋解釋,但是在@ReconField上有一些關鍵注釋需要指出。
- @Target –此注釋允許您指定注釋應應用于哪些Java元素。 可能的目標類型是ANNOTATION_TYPE,CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER和TYPE。 在我們的@ReconField批注中,它特定于FIELD級別。
- @Retention –這允許您指定注釋何時可用。 可能的值為CLASS,RUNTIME和SOURCE。 由于我們將在RUNTIME處理此批注,因此需要對其進行設置。
此數據驗證過程將對每個數據庫運行一個查詢,然后將結果映射到一個通用數據bean,該bean代表該特定類型的業務記錄的所有字段。 此映射數據Bean的每個字段上的注釋告訴處理器如何針對該特定字段及其在每個數據庫中找到的值執行數據比較。 因此,讓我們看一些如何將這些注釋用于各種數據比較配置的示例。
要驗證該值是否存在并在每個數據源中完全匹配,您只需提供字段ID和應在報告中為該字段顯示的標簽。
@ReconField(id = CUSTOMER_ID, label = "Customer ID") private String customerId;要顯示在每個數據源中找到的值,但不進行任何數據比較,則需要指定元素compareSources并將其值設置為false。
@ReconField(id = NAME, label = "NAME", compareSources = false) private String name;要驗證在特定數據源中找到的值,但不是全部,請使用元素sourcesToCompare 。 使用此選項將顯示找到的所有值,但僅對元素中列出的數據源執行任何數據比較。 處理某些數據沒有存儲在每個數據源中的情況。 ReconSource是一個枚舉,其中包含可用于比較的數據源。
@ReconField(id = PRIVATE_PLACEMENT_FLAG, label = "PRIVATE PLACEMENT FLAG", sourcesToCompare ={ ReconSource.LEGACY, ReconSource.PACE }) private String privatePlacementFlag;既然我們已經滿足了基本要求,我們就需要解決運行特定于相關領域的復雜數據比較的功能。 為此,我們將創建第二個注釋,以驅動自定義規則的處理。
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ReconCustomRule {/** * Value indicates the parameters used to instantiate a custom rule processor, the default value is no parameters. * * @return The String[] of parameters to instantiate a custom rule processor. */ String[] params() default {};/** * Value indicates the class of the custom rule processor to be used in comparing the values from each source. * * @return The class of the custom rule processor. */ Class<?> processor() default DefaultReconRule.class;}與先前的注釋非常相似, @ ReconCustomRule注釋中的最大區別是我們指定了一個在執行偵察過程時將執行數據比較的類。 您只能定義將要使用的類,因此您的處理器將必須實例化并初始化您指定的任何類。 在此批注中指定的類將需要實現自定義規則接口,規則處理器將使用該接口執行規則。
現在,讓我們看一下此注釋的幾個示例。
在此示例中,我們使用自定義規則,該規則將檢查證券交易所是否不是美國,如果是這種情況,則跳過數據比較。 為此,規則將需要檢查同一記錄上的“交換國家/地區”字段。
@ReconField(id = STREET_CUSIP, label = "STREET CUSIP", compareSources = false) @ReconCustomRule(processor = SkipNonUSExchangeComparisonRule.class) private String streetCusip;這是一個示例,其中我們為自定義規則指定了一個參數,在這種情況下,這是一個公差值。 對于此特定數據比較,要比較的值相差不能超過1,000。 通過使用參數指定容差量,這使我們可以在具有不同容差量的多個字段上使用相同的自定義規則。 唯一的缺點是這些參數是靜態的,由于注釋的性質而不能是動態的。
@ReconField(id = USD_MKT_CAP, label = "MARKET CAP USD", displayFormat = ReconDisplayFormat.NUMERIC_WHOLE, sourcesToCompare = { ReconSource.LEGACY, ReconSource.PACE, ReconSource.BOB_PRCM }) @ReconCustomRule(processor = ToleranceAmountRule.class, params = { "10000" }) private BigDecimal usdMktCap;如您所見,我們僅使用幾個相當簡單的注釋就為多個數據庫的數據驗證報告設計了相當多的靈活性。 對于這種特殊情況,注釋正在驅動數據比較處理,因此我們實際上是在評估在映射的數據bean上找到的注釋,并使用這些注釋來指導處理。
結論
關于Java注釋,它們的作用以及使用它們的規則,已有許多文章。 我想讓本文更多地關注一個示例,說明為什么您可能想要考慮使用它們并直接看到其好處。
請記住,這只是一個起點,一旦您決定創建批注,您仍然需要弄清楚如何處理它們以真正充分利用它們。 在第二部分中,我將向您展示如何使用Java反射來處理這些注釋。 在此之前,這里有一些很好的資源,可以了解有關Java注釋的更多信息:
- Java注釋教程– http://docs.oracle.com/javase/tutorial/java/annotations/
- Java注釋-http: //tutorials.jenkov.com/java/annotations.html
- 注釋的工作方式– http://java.dzone.com/articles/how-annotations-work-java
翻譯自: https://www.javacodegeeks.com/2014/07/creating-your-own-java-annotations.html
總結
以上是生活随笔為你收集整理的创建自己的Java批注的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外汇是什么?
- 下一篇: 使用Stream API的类Java产量