注解提供了一种结构化的,并且具有类型检查能力的新途径,从而使程序员能够为代码加入元数据,而不会导致代码杂乱且难以理解。如:@Override 说明继承类或实现接口方法重载。
注解是在实际的源代码级别保存所有的信息,而不是某种注释性的文字。
在Hibernate,EJB,JPA中Column实现和应用程序案例:
Column.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.FIELD})
// 目标可以指定的元素类型方法级别和域(属性)级别
@Retention(RetentionPolicy.RUNTIME)
// 保留方针为运行时级别,注解可以在运行时通过反射获得
public @interface Column {
String name() default "";
// default 关键字可以为name方法设置默认值
boolean unique() default false;
boolean nullable() default true;
boolean insertable() default true;
boolean updateable() default true;
String columnDefinition() default "";
String secondaryTable() default "";
int length() default 255;
int precision() default 0;
int scale() default 0;
}
UseCase.java
import java.lang.reflect.Field;
public class UseCase {
@Column(name = "name", length = 20, unique = true)
private String name;
@Column(name = "description", length = 100)
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public static void main(String[] args) {
Field[] fields = UseCase.class.getDeclaredFields();
for (Field field : fields) {
Column column = field.getAnnotation(Column.class);
System.out.println(column.name() + " " + column.length() + " " + column.unique());
}
}
}
控制台显示的结果为:
name 20 true
description 100 false
应用程序简单应用源码解析:
1. Field[] fields = UseCase.class.getDeclaredFields();
通过反射,UseCase.class.getDeclaredFields()获得UseCase类的class对象的声明的域。
AnnotationParser.getDeclaredFields(...)方法
public Field[] getDeclaredFields() throws SecurityException {
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
// 检查类成员访问
return copyFields(privateGetDeclaredFields(false));
// 返回一份私有获得声明域的拷贝
}
2. for (Field field : fields) {...} // 遍历fields数组
3. Column column = field.getAnnotation(Column.class); // 获得域级别的注解Annotation @Column
AnnotationParser.getAnnotation(...)方法
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
if (annotationClass == null)
throw new NullPointerException();
return (T) declaredAnnotations().get(annotationClass);// 调用声明的注解方法,获得指定@Column类型的注解
}
AnnotationParser.declaredAnnotations(...)方法
private synchronized Map<Class, Annotation> declaredAnnotations() {
if (declaredAnnotations == null) {
declaredAnnotations = AnnotationParser.parseAnnotations(
annotations, sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
getDeclaringClass());
// 注解解析,annotations为byte[],sun.misc.SharedSecrets.getJavaLangAccess().
// getConstantPool(getDeclaringClass()) 注入getDeclaringClass())即UseCase.class对象,获得Java语言访问的常量池
}
return declaredAnnotations;
}
AnnotationParser.parseAnnotations(...)方法
public static Map<Class, Annotation> parseAnnotations(byte[] paramArrayOfByte, ConstantPool paramConstantPool, Class paramClass)
{
// {code...}
return parseAnnotations2(paramArrayOfByte, paramConstantPool, paramClass);// 调用parseAnnotations2方法
// {code...}
}
AnnotationParser.parseAnnotations2(...)方法
private static Map<Class, Annotation> parseAnnotations2(byte[] paramArrayOfByte, ConstantPool paramConstantPool, Class paramClass)
{
LinkedHashMap localLinkedHashMap = new LinkedHashMap();// 声明一个链表的HashMap
ByteBuffer localByteBuffer = ByteBuffer.wrap(paramArrayOfByte);// 将字节数组装入ByteBuffer中
int i = localByteBuffer.getShort() & 0xFFFF;// 获得localByteBuffer的大小
for (int j = 0; j < i; ++j) {
Annotation localAnnotation = parseAnnotation(localByteBuffer, paramConstantPool, paramClass, false);
//解析Annotation
if (localAnnotation != null) {
Class localClass = localAnnotation.annotationType();
AnnotationType localAnnotationType = AnnotationType.getInstance(localClass);
// AnnotationType获得注解类型
if ((localAnnotationType.retention() != RetentionPolicy.RUNTIME) ||
(localLinkedHashMap.put(localClass, localAnnotation) == null)) continue;
// 说明注解@Column的保留方针必须为RUNTIME级别,并将注解类型和注解对象放入localLinkedHashMap中
throw new AnnotationFormatError("Duplicate annotation for class: " + localClass + ": " + localAnnotation);
}
}
return localLinkedHashMap;
}
AnnotationParser.parseAnnotation(...)方法
private static Annotation parseAnnotation(ByteBuffer paramByteBuffer, ConstantPool paramConstantPool, Class paramClass, boolean paramBoolean)
{
int i = paramByteBuffer.getShort() & 0xFFFF;
Class localClass1 = null;
String str1 = paramConstantPool.getUTF8At(i);//获得Column
localClass1 = parseSig(str1, paramClass);// 通过UseCase和Column解析得到@Column接口class对象
//{code...}
AnnotationType localAnnotationType = AnnotationType.getInstance(localClass1);//获得注解类型@Column
Map localMap = localAnnotationType.memberTypes();// 获得注解@Column的成员类型
LinkedHashMap localLinkedHashMap = new LinkedHashMap(localAnnotationType.memberDefaults());
//@Column的成员类型的默认值放入localLinkedHashMap
int j = paramByteBuffer.getShort() & 0xFFFF;
for (int k = 0; k < j; ++k) {
int l = paramByteBuffer.getShort() & 0xFFFF;
String str2 = paramConstantPool.getUTF8At(l);// 获得成员类型的名称如name
Class localClass2 = (Class)localMap.get(str2);
Object localObject = parseMemberValue(localClass2, paramByteBuffer, paramConstantPool, paramClass);
//获得成员的值如name的值为"name"
localLinkedHashMap.put(str2, localObject);
//{code...}
}
return annotationForMap(localClass1, localLinkedHashMap);
// 通过@Column.class对象和localLinkedHashMap创建@Column对象
}
AnnotationParser.annotationForMap(...)方法
public static Annotation annotationForMap(Class paramClass, Map<String, Object> paramMap)
{
return (Annotation)Proxy.newProxyInstance(paramClass.getClassLoader(), new Class[] { paramClass }, new AnnotationInvocationHandler(paramClass, paramMap));
// 创建@Column对象
}
看过源码实现之后,其实就是通过Java的反射机制和代理类来创建指定域(方法或者类)的注解接口对象以及他的属性。