日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

[转载] Java中的元数据

發(fā)布時(shí)間:2025/3/11 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] Java中的元数据 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考鏈接: Java中的數(shù)據(jù)類型

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

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

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

綜上所述:?

第一, 元數(shù)據(jù)以標(biāo)簽的形式存在于Java代碼中。?

第二, 元數(shù)據(jù)描述的信息是類型安全的,即元數(shù)據(jù)內(nèi)部的字段都是有明確類型的。?

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

第四, 元數(shù)據(jù)可以只存在于Java源代碼級(jí)別,也可以存在于編譯之后的Class文件內(nèi)部。?

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

Annotation定義

Annotation定義語法為:

modifiers @interface AnnotationName

{

? ?element declaration1

? ?element declaration2

}

?

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

例如下面代碼定義了一個(gè)Annotation:?

public @interface BugReport

{

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

? ?int severity() = 0;

}

?

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

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

?

元數(shù)聲明的順序沒有關(guān)系,有默認(rèn)值的元素的聲明可以不列在初始化表中,此時(shí)他們使用默認(rèn)值。例如,根據(jù)上述定義如下的三個(gè)Annotation的聲明是等價(jià)的:?

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

?

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

?

@BugReport(assignedTo="Harry")

?

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

AnnotationName(“somevalue”)?

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

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

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

如果數(shù)組中只有一個(gè)元素時(shí)可以做如下聲明:?

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

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

可以對(duì)如下對(duì)象添加Annotation:?

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

標(biāo)準(zhǔn)的Annotation?

JDK1.5提供了若干的標(biāo)準(zhǔn)Annotation來補(bǔ)充語法定義,或者標(biāo)記Annotation。標(biāo)準(zhǔn)的Annotation有以下幾個(gè):?

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

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

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

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

@Documented用來將Annotation顯示在生成的JavaDoc中。 @Inherited只能用來標(biāo)記用在類上的Annotation,用來說明被標(biāo)記的Annotation會(huì)被該類的所有子類自動(dòng)的繼承。?

Annotation應(yīng)用實(shí)例 http://www.onjava.com/pub/a/onjava/2005/01/19/metadata_validation.html by Jacob Hookom?

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

@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的校驗(yàn)要求,同時(shí)password字段也是必須的,且長度必須在6~12之間。有了這些定義之后我們能夠使用如下的代碼達(dá)到驗(yàn)證的效果:?

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

?

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

?

要能夠達(dá)到上述的要求,我們必須定義一些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();

}

?

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

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Validate {

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

}

?

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

在此設(shè)計(jì)之下看看我們?nèi)绾温暶饕粋€(gè)ValidateExpr的Annotation對(duì)象:?

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Validate(ValidateExprHandler.class)

public @interface ValidateExpr {

? ? String value();

}

?

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

// 定義了一個(gè)ValidateHandler接口,

?

// 這個(gè)接口有一個(gè)Annotation類型的模版參數(shù)

?

public interface ValidateHandler<T extends Annotation>

{

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

? ? ? throws ValidationException;

? ?public Class<T> getSettingsType();

}

?

// 一個(gè)ValidateHandler的實(shí)例,用來處理正則表達(dá)式的驗(yàn)證,

?

// 其中的Anotation類型的參數(shù)為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;

? ? }

}

?

說明:?

我們定義了一個(gè)Annotation(Validate)來標(biāo)記我們所有的校驗(yàn)用Annotation,?

同時(shí)每一個(gè)具體的校驗(yàn)用的Annotation(ValidateExpr)都必須提供一個(gè)用來具體處理?

校驗(yàn)邏輯的類(ValidateExprHandler)。?

Annotation不允許繼承,所以我們沒有辦法適用instance of的方法來識(shí)別一個(gè)校驗(yàn)框架?

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

我們同樣可以達(dá)到以上的目的。?

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

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

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

// 對(duì)一個(gè)方法和將要調(diào)用的參數(shù)值進(jìn)行校驗(yàn)?

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則說明這是我們校驗(yàn)

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

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

? ? ? if (v != null) {

? ? ? ? ?try {

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

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

? ? ? ? ? ? // 使用創(chuàng)建的ValidateHandler來做校驗(yàn)操作。

? ? ? ? ? ? // 校驗(yàn)過程中可以拋出ValidationException

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

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

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

? ? ? ? ?}

? ? ? }

? ?}

}

?

轉(zhuǎn)自https://www.cnblogs.com/liuqk/articles/2115778.html

總結(jié)

以上是生活随笔為你收集整理的[转载] Java中的元数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。