This is the 28th day of my participation in the More Text Challenge. For more details, see more text Challenge

The Spring open source framework is all about annotations

The Spring open source framework, which is all implemented through annotations, has benefited a lot from using it, so we took the time to look at how Java provides us with the annotation mechanism.


What is annotation

  • Annotations are similar to annotations that explain classes, methods, fields, and so on. Annotations are a concept introduced after jdk1.5. So to implement annotations your JDK must be at least 1.5. It can be used to create documents that track code dependencies. You can even perform basic compiler syntax checks. The format of the annotation is a class name request in the form @interface, beginning with @. As stated above, annotations are considered comments because they do not affect the semantics of the code. Annotations can exist in three ways: in source code, during compilation, and at runtime.

The role of annotations

  • Document: Generate documentation from metadata identified in the code.

  • Code analysis: Code is analyzed using metadata identified within the code.

  • Compiler checks: Allows the compiler to perform basic compiler checks by identifying metadata in the code

The basic annotation

  • We beginners in Java may not know what annotations are, but we are all rich in annotations. Let’s take a look at where we’ve used them.

Override

  • Java.lang.Override is a tag type annotation that is used as an annotation method. He shows that the method is inherited from the superclass, that is, overrides the method of the same name in the superclass. If we use @override on a method that the superclass doesn’t have at all, then our method doesn’t override the superclass’s method. We will report a compilation error at compile time.

SuppressWarnings

  • My understanding of this annotation is that it tells the compiler to ignore my possible warnings. There are actually a lot of parameters, and different parameters set different warnings
-deprecation, warning when an outdated class or method is used -unchecked, warning when an unchecked transformation is performed -fallthrough, warning when a switch block goes straight to the next situation without a break -path, Warning when there is a nonexistent path in the classpath, source file path, etc. - serial, warning when the serialVersionUID definition is missing on the serializable class - finally, warning when any finally clause fails to complete properly - all, warning about all of the aboveCopy the code

Deprecated

  • This annotation I have not actually contacted, this I searched on the Internet, the explanation is

It is used to annotate methods that should no longer be used. When programmers use these methods, they will be notified at compile time. It works in the same way as the @deprecated flag in Javadoc. An example code example using @deprecated is as follows:

  • When we write code and use methods in the JDK, sometimes we come across a method that is outdated, but we can use it. The method is implemented through this annotation. In short, it is to remind the developer that the method is outdated, and try to avoid using outdated methods.

The JDK provides a way to develop annotations

  • Now that we know more or less about annotations, how do we develop our own annotations now that Java has the concept of annotations. In the java.lang.annotation package, the JDK places annotations about annotations, and it is through the annotation class that we can develop our own annotations. Let’s first understand the annotations of annotations.

  • By looking at the source code, Including the annotation, annotationFormatError, annotationTypeMismatchExcetion, IncompleteAnnotationException these four classes occupy exception class is the basic page formatted, These are classes that we’re not going to encounter when we’re developing annotations, but they’re just JDK logic. What we really use are the remaining classes.

ElementType

  • This class is an enumeration of the fields that are used in the Target class. See Target for details

RetentionPolicy

  • This class is an enumeration, and the fields enumerated here are for use in Retention class. It is specifically stated in Retention

Documented

/** * Indicates that annotations with a type are to be documented by javadoc * and similar tools by default. This type should be used to annotate the * declarations of types whose annotations affect the use of annotated * elements by their  clients. If a type declaration is annotated with * Documented, Annotations Its annotations become part of the public API * of the annotated elements. * * @author Joshua Bloch * @since 1.5 */Copy the code
  • This is the description of documented in the JDK on the official website. What this description basically means is that the declaration of this class is used to generate an annotation on a Java document, which means that documentation can be generated on this annotation, and this is the default utility. Such annotations should be injected on the client side. At the same time, their methods become public apis.

Target

/** * Indicates the kinds of program element to which an annotation type * is applicable. If a Target meta-annotation is  not present on an * annotation type declaration, the declared type may be used on any * program element. If such a meta-annotation is present, the compiler * will enforce the specified usage restriction. * * For example, this meta-annotation indicates that the declared type is * itself a meta-annotation type. It can only be used on annotation type * declarations: * <pre> * &#064; Target(ElementType.ANNOTATION_TYPE) * public &#064; interface MetaAnnotationType { * ... * } * </pre> * This meta-annotation indicates that the declared type is intended solely * for use as a member type in complex annotation type declarations. It * cannot be used to annotate anything directly: * <pre> * &#064; Target({}) * public &#064; interface MemberType { * ... * } * </pre> * It is a compile-time error for a single ElementType constant to * appear more than once in a Target annotation. For example, the * following meta-annotation is illegal: * <pre> * &#064; Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD}) * public &#064; interface Bogus { * ... * } * </pre> */Copy the code
  • If the element specified by target does not exist, then the annotation specified by target can be used anywhere. If the element specified by target is not present, then the annotation must only be used on the specified element. The element specified by target is specified through the enumeration class ElementType, which contains the values that target can specify. The example on the official website is Target(elementType.annotation_type) to indicate that this annotation can only be used on the annotation itself. Another attribute that is not included in the ElementType enumeration is target ({}). The {} annotation is used as a member variable on the responsible annotation and cannot be used elsewhere.

  • Elementtype.constructor: Used to describe a CONSTRUCTOR

  • Elementtype. FIELD: member variables, objects, properties (including enum instances)

  • Elementtype. LOCAL_VARIABLE: Used to describe local variables

  • Elementtype. METHOD: Describes a METHOD

  • Elementtype. PACKAGE: Describes a PACKAGE

  • Elementtype. PARAMETER: Describes parameters

  • Elementtype. TYPE: Used to describe class, interface (including annotation types), or enum declarations

Retention

/** * Indicates how long annotations with the annotated type are to * be retained. If no Retention annotation is present  on * an annotation type declaration, the retention policy defaults to * {@code RetentionPolicy.CLASS}. * * <p>A Retention meta-annotation has effect only if the * meta-annotated type is used directly for annotation. It has no * effect if the meta-annotated type is used as a Member type in * another annotation type. * * @Author Joshua Bloch * @since 1.5 */Copy the code
  • The properties of this class are enumerated through the RetentionPolicy enumeration class, which is used to specify how long or when our annotation will last. This property is valid only if it is used directly on an annotation of the original annotation type. If used on a member variable in another annotation, it has no effect.

  • Retentionpolicy.source: Discarded during compilation. These annotations are no longer meaningful after compilation, so they are not written to bytecode. @Override, @Suppresswarnings are these annotations.

  • Retentionpolicy.class: discarded during CLASS loading. Useful in processing bytecode files. This is the default for annotations

- retentionPolicy.runtime: The annotation is never discarded, and the RUNTIME retains the annotation, so it can be read using reflection. Our custom annotations usually use this approach.Copy the code

Inherited

/**
 * Indicates that an annotation type is automatically inherited.  If
 * an Inherited meta-annotation is present on an annotation type
 * declaration, and the user queries the annotation type on a class
 * declaration, and the class declaration has no annotation for this type,
 * then the class's superclass will automatically be queried for the
 * annotation type.  This process will be repeated until an annotation for this
 * type is found, or the top of the class hierarchy (Object)
 * is reached.  If no superclass has an annotation for this type, then
 * the query will indicate that the class in question has no such annotation.
 *
 * <p>Note that this meta-annotation type has no effect if the annotated
 * type is used to annotate anything other than a class.  Note also
 * that this meta-annotation only causes annotations to be inherited
 * from superclasses; annotations on implemented interfaces have no
 * effect.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
Copy the code
  • The one-sentence summary is whether subclasses are allowed to inherit from the annotation

Custom annotations

  • With all that said, let’s start developing our own annotations.

Constructor annotation

/** * This annotation is valid at run time * @Author Xinhua ** / @Documented @target (elementType.constructor) @Retention(RetentionPolicy.runtime) public @interface ConstructorAnno {String decs() default "I'm the annotation for ConstructorAnno "; }Copy the code

Field notes

/** * This annotation is used to generate a doc document * this annotation is used to annotate a FIELD attribute of the class * This annotation is valid at run time * @Author Xinhua ** / @Documented @Target(elementType.field) @retention (RetentionPolicy.runtime) public @interface FieldAnno {String desc() default "Retention(RetentionPolicy.runtime) public @interface FieldAnno {String desc() default "; }Copy the code

Local variable annotation

/** * This annotation is used to generate a doc document * this annotation is used to annotate a local variable * This annotation is valid at runtime * @Author Xinhua ** / Documented @target (elementType.local_variable) @retention (retentionPolicy.runtime) public @interface LocalAnno {String desc() default ""; }Copy the code

Methods annotations

/** * This annotation is used to generate the doc document * this annotation is used to annotate the METHOD on the class * This annotation is valid at run time * @Author Xinhua ** / @Documented @target (elementType.method) @retention (retentionPolicy.runtime) public @interface MethodAnno {// Default Retention time 2017-2-28 String time() default "2017-2-28";  Boolean sex() default true; }Copy the code

Package annotations

/** * This annotation is used to generate the doc document * this annotation is used to annotate the PACKAGE * This annotation is valid at run time * @Author Xinhua ** / @Documented @target (elementType.package) @Retention(RetentionPolicy-.runtime) public @interface PackageAnno {String desc() default "I'm a Retention policy "; }Copy the code

Parameter annotation

/** * This annotation is used to generate the doc document * this annotation is used in the parameters of the class * this annotation is valid at run time * @Author Xinhua ** / @Documented @target (elementType.parameter) @Retention(RetentionPolicy.RUNTIME) public @interface StuInfo { String value() default ""; }Copy the code

Type annotations

/** * This annotation is valid at run time * @Author Xinhua ** / @Documented @target (elementType.type) @Retention(RetentionPolicy.runtime) public @interface TypeAnno {String desc() default "I am a description annotation "; }Copy the code

The entity class that is added to the test

/** * Test the effect of all types of annotation * @author Xinhua ** / public @typeanno (desc=" I am a normal class ")class User {@fieldanno private String UID; @fieldanno (@fieldanno = desc) private String UserName; @ConstructorAnno public User(){ } @MethodAnno(time="2015-12-8" , sex=false) public void doHomeWork(@StuInfo(value="211311084") String UID, @stuinfo (value=" zhang Xin-hua ")String UserName){@localanno (value=" zhang Xin-hua ") Boolean flag; }}Copy the code

The interface class added to the test

Public void doimp (@stuinfo (value=" I'm a child ")String stuType, @stuinfo (value=" I'm a child ")String things); }Copy the code

Test annotation

@author Xinhua ** / public class Junit {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException { Class<? > userClass = Class.forName("tom.change.annotation.User"); // Instantiate Object userObject = userClass.newinstance (); / / 1 - get the outermost is class annotation TypeAnno System. Out.println ("... Class notes..." ); TypeAnno typeAnno= userClass.getAnnotation(TypeAnno.class); System.out.println(typeAnno.desc()); / / 2 - field notes First of all get through reflection for class System. The properties in the field out.println ("... Field annotation......................." ); Field[] fields = userClass.getDeclaredFields(); for (Field field : fields) { FieldAnno fieldAnno = field.getAnnotation(FieldAnno.class); System.out.println(fieldAnno.desc()); } / / 3 -- method of annotation System. Out.println ("... Method notes......................." ); Method method = userClass.getMethod("doHomeWork", String.class,String.class); MethodAnno methodAnno = method.getAnnotation(MethodAnno.class); System.out.println(methodAnno.time()+"@@@"+methodAnno.sex()); / / 4 - parameter annotation realize dynamic proxy parameter System. Out.println ("... Parameter annotations......................." ); UserImp userImp=getMethodParameter(UserImp.class); UserImp.DoHouseWork(" zhang Xinhua ", "-- "); / / 5 - local variable annotation System. Out.println ("... Local variable annotations......................." ); } public static<T> T getMethodParameter(Class<T> target){return (T)Proxy.newProxyInstance(target.getClassLoader(), new Class<? >[]{target}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Annotation[][] parameterAnnotations = method.getParameterAnnotations(); for (int i=0; i<parameterAnnotations.length; i++) { Annotation[] annotations=parameterAnnotations[i]; StuInfo stuInfo =(StuInfo) annotations[0]; System.out.println(stuInfo.value()+"@@@"+args[i]); } return null; }}); }}Copy the code

rendering