Java之metadata元数据详解.docx

上传人:b****5 文档编号:6429752 上传时间:2023-01-06 格式:DOCX 页数:10 大小:19.36KB
下载 相关 举报
Java之metadata元数据详解.docx_第1页
第1页 / 共10页
Java之metadata元数据详解.docx_第2页
第2页 / 共10页
Java之metadata元数据详解.docx_第3页
第3页 / 共10页
Java之metadata元数据详解.docx_第4页
第4页 / 共10页
Java之metadata元数据详解.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

Java之metadata元数据详解.docx

《Java之metadata元数据详解.docx》由会员分享,可在线阅读,更多相关《Java之metadata元数据详解.docx(10页珍藏版)》请在冰豆网上搜索。

Java之metadata元数据详解.docx

Java之metadata元数据详解

Java之metadata(元数据)详解

也可能刚听到元数据你会有点陌生,其实任何一个使用过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@interfaceAnnotationName

{

elementdeclaration1

elementdeclaration2

...

}

modifiers指:

public,protected,private或者默认值(什么也没有)。

一个元素的声明(elementdeclaration)指:

typeelementName();

或者

typeelementName()defaultvalue;

例如下面代码定义了一个Annotation:

public@interfaceBugReport

{

StringassignedTo()default"[none]";

intseverity()=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中元素的类型必须是下述类型,或者这些类型的组合:

l基本类型(int,short,long,byte,char,double,float,orboolean)

l字符创(String)

l类(Class(可以是形如Class)的泛型类)

l枚举类型(enum)

l一个Annotation类型(annotation)

l上述类型构成的数组

如果Annotation的元素是数组,则可以做如下声明:

@BugReport(...,reportedBy={"Harry","Carl"})

如果数组中只有一个元素时可以做如下声明:

@BugReport(...,reportedBy="Joe")//OK,sameas{"Joe"}

如果Annotation元素类型为Annotation时可以做如下声明:

@BugReport(testCase=@TestCase(id="3352627"),...)

可以对如下对象添加Annotation:

lPackages

lClasses(includingenum)

lInterfaces(includingannotationinterfaces)

lMethods

lConstructors

lInstancefields(includingenumconstants)

lLocalvariables

lParametervariables

标准的Annotation

JDK1.5提供了若干的标准Annotation来补充语法定义,或者标记Annotation。

标准的Annotation有以下几个:

Annotation

使用范围

用途

 

Deprecated

所有

将目标标记为不推荐使用

 

SuppressWarnings

除了包和Annotation

禁止标记对象发出被标记的警告信息

 

Override

方法

标记这个方法重写了父类的方法

 

Target

Annotation

标记Annotation的适用范围

 

Retention

Annotation

标记Annotation最终驻留的地方

 

Documented

Annotation

该Annotation在JavaDoc文档中出现

 

Inherited

Annotation

该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与定义了一些属性,如下表所示:

驻留策略

描述

 

SOURCE

Annotation只存在于源代码中,不包括在编译生成Class文件中

 

CLASS

Annotation存在于源代码中,也存在于编译生成的Class文件中,但是在运行时这些Annotation不被JVM装载。

 

RUNTIME

Annotation存在于源代码中,也存在于编译生成的Class文件中,同时在运行时这些Annotation被装载到JVM内部,可以使用反射的机制在运行时使用。

@Documented用来将Annotation显示在生成的JavaDoc中。

@Inherited只能用来标记用在类上的Annotation,用来说明被标记的Annotation会被该类的所有子类自动的继承。

Annotation应用实例

/**

*

*byJacobHookom

*/

使用Annotation的一个例子就是建立一个简单的用户输入验证框架,使用这个框架最终用户可以以如下的方式来定义字段的校验属性:

@ValidateRequired

@ValidateEmail

publicvoidsetEmail(Stringemail){

this.email=email;

}

@ValidateRequired

@ValidateLength(min=6,max=12)

publicvoidsetPassword(Stringpassword){

this.password=password;

}

以上的代码说明,email字段是必须的,且必须满足email的校验要求,同时password字段也是必须的,且长度必须在6~12之间。

有了这些定义之后我们能够使用如下的代码达到验证的效果:

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

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

要能够达到上述的要求,我们必须定义一些Annotation,以下代码是ValidateLength和ValidateExpr的声明:

packageannotations.validates;

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

public@interfaceValidateLength{

intmin()default0;

intmax()defaultInteger.MAX_VALUE;

}

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

public@interfaceValidateExpr{

Stringvalue();

}

具体开发的过程中我们会遇到一些问题,这主要由于两方面的原意产生

第一,Annotation内部不能定义方法,只能定义一些状态。

第二,Annotation不允许使用继承(extends或者implements),这意味着我们不能在反射的过程中使用instanceof这样的功能。

为了识别出于我们定义的校验相关的Annotation我们定义了一个如下的Annotation:

packageannotations.validates;

importjava.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public@interfaceValidate{

//Classvalue();

Classvalue();

}

正如你所看到的Validate可以驻留在JVM内部,即它可以在运行时通过反射的方式使用。

同时它必须用来标记其他的Annotation,同时他有一个Class类型的value元素,这个类型必须从ValidateHandler继承而来,主要用来处理具体的验证逻辑。

在此设计之下看看我们如何声明一个ValidateExpr的Annotation对象:

packageannotations.validates;

importjava.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Validate(ValidateExprHandler.class)

public@interfaceValidateExpr{

Stringvalue();

}

ValidateExpr的前两个Annotation不用多讲,主要说说@Validate(ValidateExprHandler.class)

的含义,这样解决了我们前边提到的两个问题,第一、我们可以看看一个Annotation是否有Validate类型的Annotation来确定这个Annotation是不是我们校验框架内部使用的Annotation。

同时我们也提供了一个具体的类ValidateExprHandler来处理校验逻辑。

接下来我们看看ValidateExprHandler的实现:

------------------------------------------------------------------------------------------------------------------------------------------

packageannotations.validates;

importjava.lang.annotation.Annotation;

importjavax.xml.bind.ValidationException;

//定义了一个ValidateHandler接口,

//这个接口有一个Annotation类型的模版参数

publicinterfaceValidateHandler{

publicvoidvalidate(Tsettings,Objectvalue)throwsValidationException;

publicClassgetSettingsType();

}

------------------------------------------------------------------------------------------------------------------------------------------

packageannotations.validates;

importjava.util.regex.Pattern;

importjavax.xml.bind.ValidationException;

//一个ValidateHandler的实例,用来处理正则表达式的验证,

//其中的Anotation类型的参数为ValidateExpr

publicclassValidateExprHandlerimplementsValidateHandler{

publicvoidvalidate(ValidateExprsettings,Objectvalue)

throwsValidationException{

//TODOAuto-generatedmethodstub

Stringi=(value!

=null)?

value.toString():

"";

if(!

Pattern.matches(settings.value(),i)){

thrownewValidationException(i+"doesnotmatchthepattern"

+settings.value());

}

}

publicClassgetSettingsType(){

//TODOAuto-generatedmethodstub

returnValidateExpr.class;

}

}

------------------------------------------------------------------------------------------------------------------------------------------

说明:

1.我们定义了一个Annotation(Validate)来标记我们所有的校验用Annotation,

同时每一个具体的校验用的Annotation(ValidateExpr)都必须提供一个用来具体处理

校验逻辑的类(ValidateExprHandler)。

2.Annotation不允许继承,所以我们没有办法适用instanceof的方法来识别一个校验框架

使用的Annotation,但是通过对我们使用的校验用的Annotation添加Annotation(Validate)

我们同样可以达到以上的目的。

3.ValidateHandler接口允许一个校验用的Annotation将具体的校验功能已代理的方式让其它的类来完成。

我们可以使用如下的方式来处理校验的具体过程:

说明:

在JDK1.5中Method实现了AnnotatedElement接口,我们可以使用AnnotatedElement来做处理操作

//对一个方法和将要调用的参数值进行校验

publicstaticvoidvalidate(AnnotatedElementelement,Objectvalue){

Validatev;

ValidateHandlervh;

Annotationa;

//从该方法上返回所有的Annotation

Annotation[]annotations=element.getAnnotations();

for(inti=0;i<annotations.length;i++){

//如果该Annotation有类型为Validate的Annotation,则说明这是我们校验

//框架所使用的Annotation。

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

if(v!

=null){

try{

//使用Annotation中定义的ValidateHandler类来生成ValidateHandler的实例

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

//使用创建的ValidateHandler来做校验操作。

//校验过程中可以抛出ValidationException

vh.validate(annotations[i],value);

}catch(Exceptione){

//TODO:

handleexception

e.printStackTrace();

}

}

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1