Annotations provide a structured and new way of checking types, so that programmers can add metadata to the code without causing code clutter and difficulty in understanding. For example, @ Override indicates the inheritance class or interface method overloading.
Annotation stores all information at the actual source code level, rather than comments.
Column implementation and application cases in hibernate, EJB, and JPA:
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}) // specifies the element type, method level, and domain (attribute) level @ retention (retentionpolicy. runtime) // The retention policy is at the runtime level. Annotations can get public @ interface column {string name () Default "through reflection at runtime ""; // The default keyword can be set for the name method. The default value is 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()); } }}
The console displays the following results:
Name 20 true
Description 100 false
Simple application source code analysis:
1. Field [] fields = UseCase. class. getDeclaredFields ();
Through reflection, UseCase. class. getDeclaredFields () obtains the declared domain of the class Object of the UseCase class.
AnnotationParser. getDeclaredFields (...) Method
Public Field [] getDeclaredFields () throws SecurityException {checkMemberAccess (Member. DECLARED, ClassLoader. getCallerClassLoader (); // check if the class member accesses return copyFields (privateGetDeclaredFields (false); // return a copy of the private object to obtain the declared domain}
2. for (Field field: fields) {...} // traverse the fields Array
3. Column column = field. getAnnotation (Column. class); // obtain the field-level Annotation @ Column
AnnotationParser. getAnnotation (...) Method
Public <T extends Annotation> T getAnnotation (Class <T> annotationClass) {if (annotationClass = null) throw new NullPointerException (); return (T) declaredAnnotations (). get (annotationClass); // call the declared annotation method to obtain the annotation of the specified @ Column type}
Annotationparser. declaredannotations (...) Method
Private synchronized Map <class, annotation> declaredannotations () {If (declaredannotations = NULL) {declaredannotations = annotationparser. parseannotations (annotations, Sun. misc. sharedsecrets. getjavalangaccess (). getconstantpool (getdeclaringclass (), getdeclaringclass (); // annotation parsing. Annotations are byte [], Sun. misc. sharedsecrets. getjavalangaccess (). // getconstantpool (getdeclaringclass () injection getdeclaringclass () is usecase. class Object to obtain the constant pool accessed by the Java language} return declaredannotations ;}
Annotationparser. parseannotations (...) Method
Public static Map <class, annotation> parseannotations (byte [] paramarrayofbyte, constantpool paramconstantpool, class paramclass) {// {code ...} return parseannotations2 (paramarrayofbyte, paramconstantpool, paramclass); // call the parseannotations2 method // {code ...}}
AnnotationParser. parseAnnotations2 (...) Method
Private Static Map <class, annotation> parseannotations2 (byte [] paramarrayofbyte, constantpool paramconstantpool, class paramclass) {linkedhashmap local1_hashmap = new linkedhashmap (); // declare the hashmap bytebuffer localbytebuffer = bytebuffer of a linked list. wrap (paramarrayofbyte); // load the byte array into bytebuffer int I = localbytebuffer. getshort () & 0 xFFFF; // obtain the localbytebuffer size for (Int J = 0; j <I ;++ J) {annotation L Ocalannotation = parseannotation (localbytebuffer, paramconstantpool, paramclass, false); // parse annotation if (localannotation! = NULL) {class localclass = localannotation. annotationtype (); annotationtype localannotationtype = annotationtype. getinstance (localclass); // annotationtype obtain annotation type if (localannotationtype. Retention ()! = Retentionpolicy. runtime) | (local1_hashmap. put (localclass, localannotation) = NULL) continue; // specifies that the retention policy of annotation @ column must be at the runtime level, add the annotation type and annotation object to localjavashashmap. Throw new annotationformaterror ("Duplicate annotation for class:" + localclass + ":" + localannotation);} return local#hashmap ;}
AnnotationParser. parseAnnotation (...) Method
Private static Annotation parseAnnotation (ByteBuffer paramByteBuffer, ConstantPool paramConstantPool, Class paramClass, boolean paramBoolean) {int I = paramByteBuffer. getShort () & 0 xFFFF; Class localClass1 = null; String str1 = paramConstantPool. getUTF8At (I); // obtain Column localClass1 = parseSig (str1, paramClass); // obtain the @ Column Interface class Object through UseCase and Column parsing // {code ...} annotationType localAnnotationType = AnnotationType. getInstance (localClass1); // obtain the annotation type @ Column Map localMap = localAnnotationType. memberTypes (); // obtain the annotation @ Column member type LinkedHashMap local1_hashmap = new LinkedHashMap (localAnnotationType. memberDefaults (); // Add the default value of the member type of @ Column to local1_hashmap int j = paramByteBuffer. getShort () & 0 xFFFF; for (int k = 0; k <j; ++ k) {int l = paramByteBuffer. getShort () & 0 xFFFF; String str2 = paramConstantPool. getUTF8At (l); // obtain the name of the member type, such as name Class localClass2 = (Class) localMap. get (str2); Object localObject = parseMemberValue (localClass2, paramByteBuffer, paramConstantPool, paramClass); // obtain the value of a member, for example, "name" localLinkedHashMap. put (str2, localObject); // {code ...}} return annotationForMap (localClass1, localLinkedHashMap); // @ Column. class Object and localLinkedHashMap create @ Column object}
AnnotationParser. annotationForMap (...) Method
Public static Annotation annotationForMap (Class paramClass, Map <String, Object> paramMap) {return (Annotation) Proxy. newProxyInstance (paramClass. getClassLoader (), new Class [] {paramClass}, new AnnotationInvocationHandler (paramClass, paramMap); // create @ Column object}
After reading the source code implementation, the Java reflection mechanism and proxy class are used to create annotation interface objects for the specified domain (method or class) and their attributes.
In fact, in Java, these things seem very difficult to implement (for 'yourself '), but you can look at the source code and look at his design philosophy, you may have some insights and learning to understand the implementation of Java APIs. This requires patience and patience.