Java与元数据
元数据是关于数据的数据。在编程语言上下文中,元数据是添加到程序元素如方法、字段、类和包上的额外信息。
元数据的作用
一般来说,元数据可以用于创建文档,跟踪代码中的依赖性,执行编译时检查,代码分析。
元数据还可用于协助程序元素与框架或者EJB、EMF 和 TestNG这样的工具之间的通信。EJB 3.0就广泛地应用了Java元数据,通过元数据来实现声明性请求企业服务,依赖性以及资源注入,消除了严格的EJB组件模型约束,并且取代了复杂的XML配置文件。
元数据甚至使我们可以不用修改核心语言,就能够在 Java 语言中添加新功能,使核心语言成为一种开放式语言。在纯面向对象的语言中实现AOP就是使用元数据进行语言扩展的一个很好的例子。AspectWerkz、JBoss AOP以及AspectJ5 使用元数据将类的语义转换为一个aspect、将数据字段转换为一个pointcut、将方法转换为一个advice,等等。
ava平台的元数据
Java 元数据(Annotation)是 J2SE 5.0 (研发历时近三年,于2004年9月30日正式发布,代号为“Tiger”)新增加的功能之一,它在JSR-175规范中有详细定义。该机制允许在 Java 代码中添加自定义注释,并允许通过反射(reflection),以编程方式访问元数据注释。通过提供为程序元素附加额外数据的标准方法,元数据功能具有简化和改进许多应用程序开发领域的潜在能力,其中包括配置管理、框架实现和代码生成。
Annotation不直接影响程序的语义。然而,开发和部署工具可以读取这些注释,并以某种形式处理这些注释,可能生成其他 Java源程序、XML配置文件或者要与包含注释的程序一起使用的其他组件,从而影响运行状态的程序的语义。注释可以从源代码中读取,从编译后的.class文件中读取,也可以通过反射机制在运行时读取。
Annotation具有以下的一些特点:
元数据以标签的形式存在于Java代码中。
元数据描述的信息是类型安全的,即元数据内部的字段都是有明确类型的。
元数据需要编译器之外的工具额外的处理用来生成其它的程序部件。
元数据可以只存在于Java源代码级别,也可以存在于编译之后的Class文件内部。
们可以使用JAVA内置的注释内型,如果觉得不够用,可以定义自己的注释内型,定义如下
/*
* MyType.java
*
* Created on 2006年12月7日, 下午3:40
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package
testAnno;
/**
*
*
@author
lbf
*/
import
java.lang.annotation.
*
;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public
@
interface
MyType {
String authorName();
String lastModified();
String bugFixes()
default
"
ok
"
;
}
这里我定义了一个我自己的注释类,声明方式和声明接口差不多,只不过在interface前面多了一个@符号.
注释类也可以用注释类注释,如此下去.
@Retention(RetentionPolicy.RUNTIME)
这句表示它的保存范围是到RUNTIME,也就是运行时,这样在类运行的时候,我们也可以取到有关它的信息.
@Target({ElementType.TYPE,ElementType.METHOD})
这句表示它的适用对象,它可以用在哪里地方,我这里定义的是它可以用在类的定义和方法的定义上
然后我们看我们是怎么为我们写的类加上注释的
/*
* Test1.java
*
* Created on 2006年12月7日, 下午3:34
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package
testAnno;
/**
*
*
@author
lbf
*/
import
java.lang.annotation.
*
;
@MyType(authorName
=
"
hadeslee
"
,lastModified
=
"
20061207
"
)
public
class
Test1 {
/**
Creates a new instance of Test1
*/
public
Test1() {
}
@Deprecated
@MyType(authorName
=
"
hadeslee
"
,lastModified
=
"
20061207
"
,bugFixes
=
"
what
"
)
public
void
doSth(){
}
@MyType(authorName
=
"
hadeslee
"
,lastModified
=
"
20061207
"
,bugFixes
=
"
what
"
)
public
void
doAnother(){
}
}
加了元数据的类和不加元数据的类差不多,只不过如果你的元数据注释如果是运行时的话,你的类文件可能会比不加元数据大一些,因为它必须把一些注释的信息写入到class文件中去,我们已经注释了我们的类,现在我们来看一下,我们如何去取我们的注释,
/*
* GetAnno.java
*
* Created on 2006年12月7日, 下午3:46
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package
testAnno;
/**
*
*
@author
lbf
*/
import
java.lang.annotation.
*
;
import
java.lang.reflect.
*
;
public
class
GetAnno {
/**
Creates a new instance of GetAnno
*/
public
GetAnno() {
}
public
static
void
main(String[] args)
throws
Exception {
Test1 t
=
new
Test1();
Class c
=
Test1.
class
;
Annotation[] as
=
c.getDeclaredAnnotations();
for
(Annotation an:as){
System.out.println(
"
类Test1的注释
"
+
an);
}
Method med
=
c.getDeclaredMethod(
"
doSth
"
);
Annotation[] ass
=
med.getDeclaredAnnotations();
for
(Annotation an:ass){
Class
<!--/
sp
-->
extends
Annotation
>
clazz
=
an.annotationType();
Annotation[] ased
=
clazz.getAnnotations();
for
(Annotation ad:ased){
System.out.println(
"
注释的注释:
"
+
ad);
}
System.out.println(
"
方法doSth的注释:
"
+
an);
}
}
}
此程序输出如下
类Test1的注释@testAnno.MyType(bugFixes=ok, authorName=hadeslee, lastModified=20061207)
注释的注释:@java.lang.annotation.Documented()
注释的注释:@java.lang.annotation.Retention(value=RUNTIME)
方法doSth的注释:@java.lang.Deprecated()
注释的注释:@java.lang.annotation.Retention(value=RUNTIME)
注释的注释:@java.lang.annotation.Target(value=[TYPE, METHOD])
方法doSth的注释:@testAnno.MyType(bugFixes=what, authorName=hadeslee, lastModified=20061207)