[转载] 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.mzph.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 …