[轉載] Java中的元數據

參考鏈接: Java中的數據類型

元數據 也可能剛聽到元數據你會有點陌生,其實任何一個使用過struts,ejb或者hibernate的開發人員都在不知不覺中使用元數據。所謂的元數據是指用來描述數據的數據,更通俗一點就是描述代碼間關系,或者代碼與其它資源(例如數據庫表)之間內在聯系得數據,對Struts來說就是struts-config.xml,對ejb來說就是ejb-jar.xml和廠商自定義的xml文件,對hibernate來說就是hbm文件。?

但是現有的所有的以xml或者其它方式存在的元數據文件都有以下一些不便之處,第一,與被描述的文件分離,不利于一致性維護。第二,所有的這些文件都是ascii文件,沒有顯示的類型支持。基于元數據的廣泛應用JDK1.5引入了Annotation的概念來描述元數據。使用過.net的開發人員一定很熟悉元數據的概念,元數據的概念在.net中成為Attribute。?

在Java中元數據以標簽的形式存在于Java代碼中,元數據標簽的存在并不影響程序代碼的編譯和執行,它只是被用來生成其它的文件或針在運行時知道被運行代碼的描述信息。?

綜上所述:?

第一, 元數據以標簽的形式存在于Java代碼中。?

第二, 元數據描述的信息是類型安全的,即元數據內部的字段都是有明確類型的。?

第三, 元數據需要編譯器之外的工具額外的處理用來生成其它的程序部件。?

第四, 元數據可以只存在于Java源代碼級別,也可以存在于編譯之后的Class文件內部。?

如何創建元數據類型 像各種類有可以定義不同的類型一樣,原數據也可以定義不同的類型。現在為止,Java語言中已經有了四種種的類型:對象類(class),枚舉(enum),接口(interface)和元數據(@interface)。其實Java中的元數據的概念即吸收了.Net中Attribute的概念,有吸收了.net中property的概念。?

Annotation定義

Annotation定義語法為:

modifiers @interface AnnotationName

{

? ?element declaration1

? ?element declaration2

}

?

modifiers指:public,protected,private或者默認值(什么也沒有)。 一個元素的聲明(element declaration)指: type elementName(); 或者 type elementName() default value;?

例如下面代碼定義了一個Annotation:?

public @interface BugReport

{

? ?String assignedTo() default "[none]";

? ?int severity() = 0;

}

?

而可以通過以下的方式來聲明Annotation:?

AnnotationName(elementName1=value1, elementName2=value2, . . .)

?

元數聲明的順序沒有關系,有默認值的元素的聲明可以不列在初始化表中,此時他們使用默認值。例如,根據上述定義如下的三個Annotation的聲明是等價的:?

@BugReport(assignedTo="Harry", severity=0)

?

@BugReport(severity=0, assignedTo="Harry")

?

@BugReport(assignedTo="Harry")

?

那些只有一個元素,且元素名字叫value的Annotation可以使用如下的方式聲明:?

AnnotationName(“somevalue”)?

Annotation中元素的類型必須是下述類型,或者這些類型的組合:?

基本類型 (int, short, long, byte, char, double, float, or boolean)字符創(String)類(Class (可以是形如 Class<? extends MyClass>)的泛型類)枚舉類型(enum)一個Annotation類型(annotation)上述類型構成的數組

如果Annotation的元素是數組,則可以做如下聲明: @BugReport(. . ., reportedBy={“Harry”, “Carl”})?

如果數組中只有一個元素時可以做如下聲明:?

@BugReport(. . ., reportedBy=“Joe”) // OK, same as {“Joe”} 如果Annotation元素類型為Annotation時可以做如下聲明:?

@BugReport(testCase=@TestCase(id=“3352627”), . . .)?

可以對如下對象添加Annotation:?

PackagesClasses (including enum)Interfaces (including annotation interfaces)MethodsConstructorsInstance fields (including enum constants)Local variablesParameter variables

標準的Annotation?

JDK1.5提供了若干的標準Annotation來補充語法定義,或者標記Annotation。標準的Annotation有以下幾個:?

Annotation使用范圍用途Deprecated所有將目標標記為不推薦使用SuppressWarnings除了包和Annotation禁止標記對象發出被標記的警告信息Override方法標記這個方法重寫了父類的方法TargetAnnotation標記Annotation的適用范圍RetentionAnnotation標記Annotation最終駐留的地方DocumentedAnnotation該Annotation在JavaDoc文檔中出現InheritedAnnotation該Annotation默認被使用該Annotation的所有子類繼承

?下面具體講解標準Annotation的用法。 常用的Annotation包括以下三個:@Deprecated @SuppressWarnings @Override,他們的用途分別如上表所示。 以下說明的Annotation有一個共同的特點就是他們都只能用在Annotation的聲明上。 @Target用來標記Annotation適用的范圍,@Target有一些預定義的屬性,如下表所示: 類型|適用范圍 -|-| ANNOTATION_TYPE|只能用在Annotation的聲明中 PACKAGE|用在包上 TYPE|類(包括枚舉)或者接口(包括Annotation) METHOD|方法 CONSTRUCTOR|構造方法 FIELD|字段(包含枚舉內部的常量) PARAMETER|方法或者構造方法的參數 LOCAL_VARIABLE|本地變量?

?@Retention用來標記Annotation在那些范圍(源代碼,類文件或者運行時)內是可用的。@Retention與定義了一些屬性,如下表所示:?

駐留策略描述SOURCEAnnotation只存在于源代碼中,不包括在編譯生成Class文件中CLASSAnnotation存在于源代碼中,也存在于編譯生成的Class文件中,但是在運行時這些Annotation不被JVM裝載。RUNTIMEAnnotation存在于源代碼中,也存在于編譯生成的Class文件中,同時在運行時這些Annotation被裝載到JVM內部,可以使用反射的機制在運行時使用。

@Documented用來將Annotation顯示在生成的JavaDoc中。 @Inherited只能用來標記用在類上的Annotation,用來說明被標記的Annotation會被該類的所有子類自動的繼承。?

Annotation應用實例 http://www.onjava.com/pub/a/onjava/2005/01/19/metadata_validation.html by Jacob Hookom?

使用Annotation的一個例子就是建立一個簡單的用戶輸入驗證框架,使用這個框架最終用戶可以以如下的方式來定義字段的校驗屬性:?

@ValidateRequired

@ValidateEmail

public void setEmail(String email) {

? ? ? ? this.email = email;

}

?

@ValidateRequired

@ValidateLength(min=6,max=12)

public void setPassword(String password) {

? ? ? ? this.password = password;

}

?

以上的代碼說明,email字段是必須的,且必須滿足email的校驗要求,同時password字段也是必須的,且長度必須在6~12之間。有了這些定義之后我們能夠使用如下的代碼達到驗證的效果:?

Validator.validate(loginBean, "email", "yourname@onjava.com"); //pass

?

Validator.validate(loginBean, "password", ""); // failure

?

要能夠達到上述的要求,我們必須定義一些Annotation,以下代碼是ValidateLength和ValidateExpr的聲明:?

// Example @ValidateLength(min=6,max=8)

public @interface ValidateLength {

? ? int min() default 0;

? ? int max() default Integer.MAX_VALUE;

}

// Example @ValidateExpr("^(\\w){0,2}$");

public @interface ValidateExpr {

? ? ? ? String value();

}

?

具體開發的過程中我們會遇到一些問題,這主要由于兩方面的原意產生第一,Annotation內部不能定義方法,只能定義一些狀態。第二,Annotation不允許使用繼承(extends或者implements),這意味著我們不能在反射的過程中使用instance of這樣的功能。為了識別出于我們定義的校驗相關的Annotation我們定義了一個如下的Annotation:?

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Validate {

? ? Class<? extends ValidateHandler> value();

}

?

正如你所看到的Validate可以駐留在JVM內部,即它可以在運行時通過反射的方式使用。同時它必須用來標記其他的Annotation,同時他有一個Class類型的value元素,這個類型必須從ValidateHandler繼承而來,主要用來處理具體的驗證邏輯。?

在此設計之下看看我們如何聲明一個ValidateExpr的Annotation對象:?

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Validate(ValidateExprHandler.class)

public @interface ValidateExpr {

? ? String value();

}

?

ValidateExpr的前兩個Annotation不用多講,主要說說@Validate(ValidateExprHandler.class)的含義,這樣解決了我們前邊提到的兩個問題,第一我們可以看看一個Annotation是否有Validate類型的Annotation來確定這個Annotation是不是我們校驗框架內部使用的Annotation。同時我們也提供了一個具體的類ValidateExprHandler來處理校驗邏輯。 接下來我們看看ValidateExprHandler的實現:?

// 定義了一個ValidateHandler接口,

?

// 這個接口有一個Annotation類型的模版參數

?

public interface ValidateHandler<T extends Annotation>

{

? ?public void validate(T settings, Object value)

? ? ? throws ValidationException;

? ?public Class<T> getSettingsType();

}

?

// 一個ValidateHandler的實例,用來處理正則表達式的驗證,

?

// 其中的Anotation類型的參數為ValidateExpr

?

public class ValidateExprHandler implements ValidateHandler<ValidateExpr> {

? ??

? ? public void validate(ValidateExpr settings, Object value) throws ValidationException {

? ? ? ? String i = (value != null) ? value.toString() : "";

? ? ? ? if (!Pattern.matches(settings.value(), i)) {

? ? ? ? ? ? throw new ValidationException(i

? ? ? ? ? ? ? ? ? ? + " does not match the pattern "

? ? ? ? ? ? ? ? ? ? + settings.value());

? ? ? ? }

? ? }

? ? public Class<ValidateExpr> getSettingsType() {

? ? ? ? return ValidateExpr.class;

? ? }

}

?

說明:?

我們定義了一個Annotation(Validate)來標記我們所有的校驗用Annotation,?

同時每一個具體的校驗用的Annotation(ValidateExpr)都必須提供一個用來具體處理?

校驗邏輯的類(ValidateExprHandler)。?

Annotation不允許繼承,所以我們沒有辦法適用instance of的方法來識別一個校驗框架?

使用的Annotation,但是通過對我們使用的校驗用的Annotation添加Annotation(Validate)?

我們同樣可以達到以上的目的。?

ValidateHandler接口允許一個校驗用的Annotation將具體的校驗功能已代理的方式讓其它的類來完成。?

我們可以使用如下的方式來處理校驗的具體過程:?

說明:在JDK1.5中Method實現了AnnotatedElement接口,我們可以使用AnnotatedElement來做處理操作?

// 對一個方法和將要調用的參數值進行校驗?

public static void validate(AnnotatedElement element, Object value)

? ? ? ? ? ? throws ValidationException

{

? ?Validate v;

? ?ValidateHandler vh;

? ?Annotation a;

? ?// 從該方法上返回所有的Annotation

? ?Annotation[] ma = element.getAnnotations();

? ?for (int i = 0; i < ma.length; i++) {

? ? ? // 如果該Annotation有類型為Validate的Annotation則說明這是我們校驗

? ? ? // 框架所使用的Annotation。

? ? ? v = ma[i].annotationType().getAnnotation(Validate.class);

? ? ? if (v != null) {

? ? ? ? ?try {

? ? ? ? ? ? // 使用Annotation中定義的ValidateHandler類來生成ValidateHandler的實例。

? ? ? ? ? ? vh = v.value().newInstance();

? ? ? ? ? ? // 使用創建的ValidateHandler來做校驗操作。

? ? ? ? ? ? // 校驗過程中可以拋出ValidationException

? ? ? ? ? ? vh.validate(ma[i], value);

? ? ? ? ?} catch (InstantiationException ie) {

? ? ? ? ?} catch (IllegalAccessException iae) {

? ? ? ? ?}

? ? ? }

? ?}

}

?

轉自https://www.cnblogs.com/liuqk/articles/2115778.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/540400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/540400.shtml
英文地址,請注明出處:http://en.pswp.cn/news/540400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

云時代 揭開性能監測戰略的隱秘優勢

云時代的性能監測戰略 能夠對各種變化做出快速響應而不偏離重心和企業發展動力&#xff0c;正逐漸成為各行各業、各種規模企業的奮斗目標。業務敏捷性通常是運營良好&#xff0c;可實現盈利的企業標志。實現這一目標意味著公司已經成功地利用業務關鍵型技術來提高生產率&#x…

[轉載] java 枚舉Enum源碼解析

參考鏈接&#xff1a; 使用Java枚舉 應用場景 枚舉是單例模式中的一種。面試官系統之設計模式&#xff08;單例模式&#xff09; 簡單來講就是只能實例化一次&#xff0c;線程安全且性能高。枚舉通常用來列舉一個類型的有限實例集合&#xff0c;我們可以使用常量集來實現&…

聊聊全站HTTPS帶來的技術挑戰

日前寫的文章里了討論了數據傳輸的安全性的問題&#xff0c;最后一部分提到了通過HTTPS解決數據傳輸安全性的方案。那么一個新問題又來了&#xff0c;實施全站HTTPS的過程中&#xff0c;我們可能會遇到哪些技術問題?所以我今天和大家一起來算一下這個賬&#xff0c;將技術成本…

[轉載] spring mvc自定義int枚舉轉換器

參考鏈接&#xff1a; Java中具有自定義值的枚舉 2019獨角獸企業重金招聘Python工程師標準>>> public class MyIntegerEnumConverters { WritingConverter public static class EnumToIntegerConverter implements Converter<IntEnumConvertable, String> {…

使用BufferedImage進行漸變色操作

序 本文主要簡述一下如何使用BufferedImage進行漸變色操作。 GradientPaint java/awt/GradientPaint.java public class GradientPaint implements Paint {Point2D.Float p1;Point2D.Float p2;Color color1;Color color2;boolean cyclic;//...... } 這個是生成漸變色的關…

[轉載] Java中的字符串處理

參考鏈接&#xff1a; Java中的StringBuffer appendCodePoint()方法以及示例 JDK8在線Api中文手冊 JDK8在線Api英文手冊 Java中的字符串處理 1.1 String類的構造函數1.2 字符串的長度1.3 特殊的字符串操作1.3.1 字符串字面值1.3.2 字符串連接1.3.3 字符串和其他數據類型的連…

MySQL循環語句之while循環測試

轉自&#xff1a;http://www.nuoweb.com/database/7614.htmlMySQL有循環語句操作&#xff0c;while 循環、loop循環和repeat循環&#xff0c;目前我只測試了 while 循環&#xff0c;下面與大家分享下mysql 操作同樣有循環語句操作&#xff0c;網上說有3中標準的循環方式&#x…

[轉載] JAVA環境變量配置

參考鏈接&#xff1a; Java中的變量 安裝JDK(1.8) Oracle官網 下載jdk 百度網盤window版本 提取碼&#xff1a;o99i win 10環境變量配置 在電腦桌面 右鍵點擊 此電腦 的 屬性 選項 選擇 高級系統設置 > 然后點擊 環境變量 選項 點擊 系統變量 下的 新建 按鈕&#xf…

[轉載] Java中的變量和常量

參考鏈接&#xff1a; Java中的變量范圍 在程序中存在大量的數據來代表程序的狀態&#xff0c;其中有些數據在程序的運行過程中值會發生改變&#xff0c;有些數據在程序運行過程中值不能發生改變&#xff0c;這些數據在程序中分別被叫做變量和常量。 在實際的程序中&#xf…

4.3/4.4 磁盤分區

2019獨角獸企業重金招聘Python工程師標準>>> 添加虛擬磁盤 第一步&#xff0c;選擇虛擬機中的“設置” 第二步&#xff0c;選擇“添加硬盤” 第三步&#xff0c;選擇_SCSI &#xff08;推薦&#xff09; # 保持默認 第四步&#xff0c;選擇“創建新的虛擬磁盤…

[轉載] java(三)對象的序列化與static、final關鍵字

參考鏈接&#xff1a; Java中的final最終變量 java對象的序列化 Java序列化是指把Java對象轉換為字節序列的過程&#xff1b;而Java反序列化是指把字節序列恢復為Java對象的過程。java中存有Cloneable接口&#xff0c;實現此接口的類都具有被拷貝能力&#xff0c;比new一個對象…

RoboMaster 2017:機器人版的「王者農藥」,工程師們的競技時代

8月6日晚&#xff0c;第十六屆全國大學生機器人大賽 RoboMaster 2017機甲大師賽在華潤深圳灣體育中心“春繭”體育館舉行&#xff0c;關于這個比賽的盛況已經無需贅述&#xff0c;去年雷鋒網參加上屆比賽時&#xff0c;報道的是「像看了一場演唱會」&#xff0c;如果用演唱會來…

[轉載] 詳解Java中的泛型

參考鏈接&#xff1a; Java中具有泛型的有界類型 1、什么是泛型 泛型&#xff0c;即“參數化類型”。一提到參數&#xff0c;最熟悉的就是定義方法時有形參&#xff0c;然后調用此方法時傳遞實參。那么參數化類型怎么理解呢&#xff1f;顧名思義&#xff0c;就是將類型由原來…

【初學者必讀】:前端工程師的知識體系

下圖是前端工程師圖解&#xff1a; 前端開發的核心是HTML CSS JavaScript。本質上它們構成一個MVC框架&#xff0c;即HTML作為信息模型&#xff08;Model&#xff09;&#xff0c;CSS控制樣式&#xff08;View&#xff09;&#xff0c;JavaScript負責調度數據和實現某種展現邏…

[轉載] Java面試題大全(2020版)

參考鏈接&#xff1a; Java中的循環 發現網上很多Java面試題都沒有答案&#xff0c;所以花了很長時間搜集整理出來了這套Java面試題大全&#xff0c;希望對大家有幫助哈~ 本套Java面試題大全&#xff0c;全的不能再全&#xff0c;哈哈~ 博主已將以下這些面試題整理成了一個…

使用Prometheus監控Cloudflare的全球網絡

Matt Bostock在SRECON 2017歐洲大會的演講中&#xff0c;介紹了如何使用Prometheus實現對CloudFlare分布于全球的架構和網絡的監控。Prometheus是一種基于度量進行監控的工具&#xff0c;CloudFlare是一家CDN、DNS和DDoS防御&#xff08;Mitigation&#xff09;服務提供商。\\基…

[轉載] Java-forEach增強for循環是值傳遞規則詳解

參考鏈接&#xff1a; Java中的for-each循環 1. 引入 正如Java語法意義&#xff0c;變量的傳遞只有值傳遞&#xff0c;雖然變量分為引用變量和基本類型變量&#xff0c;前者更像C中的地址概念。 在學習Lambda表達式的時候&#xff0c;遇到了試圖在增強for循環中對原鏈表元素重…

開始吧

2019獨角獸企業重金招聘Python工程師標準>>> 寫C三年有余&#xff0c;在技術方面也算小有所成。準備在這里分享一些C進階、Python、Golang技術文章。 CSDN博客地址&#xff1a; http://blog.csdn.net/godmaycry 以后博客同步更新。 轉載于:https://my.oschina.net/u…

[轉載] 常用應屆生Java開發筆試面試題(更新中)

參考鏈接&#xff1a; Java中的循環的重要事項 Java開發面試題 Java基礎篇Java8大基本數據類型Java的三大特性面向對象如果讓你推銷一款Java產品&#xff0c;你會怎么推銷呢&#xff1f;&#xff08;java的特點&#xff09;JVM與字節碼JDK與JREStringBuilder和StringBuffer的區…

java/javascript 時間操作工具類

一、java 時間操作工具類 import org.springframework.util.StringUtils;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List;/*** 時間操作工具類** author zwq**/ public …