Java ape’s lifeblood!

Annotations have become the lifeblood of Java programmers since the Java EE framework entered the Spring Boot era, and annotation-oriented programming has become a daily routine.

In other words: we can’t do anything without annotations.

Isn’t it dangerous!

So this article to Lao Lao about the relevant operation of annotations, and begin to write a note to feel the principle. When the primal thing is mastered, the mind will naturally stop panicking.


The rationale for annotations

First of all, annotating is not rocket science and there is no need to be afraid of it!

As its name implies, its original meaning is used to make annotations: you can make a special mark in the position of class, field variables, methods, interfaces, etc., for the subsequent work such as code generation, data verification, resource integration, etc.

Yeah, it’s just for marking!

Once annotations have been annotated to the code, we can then use Java’s powerful reflection mechanism to dynamically retrieve annotation information at runtime, allowing us to perform a lot of other logic and automate the desired work.

Therefore, reflection must be learned well!


Come on!Start making a note

In my previous post, “Do you still write complex parameter checks?” As mentioned in Spring, Spring itself provides a number of handy annotations that can be used to easily validate data.

For example, we want to validate the Student class without annotation support:

                            
     

    public class Student {

    private Long id; / / student id

    private String name; / / name

    private String mobile; // Mobile phone number (11 digits)

    }

Copy the code

We can only verify by handwriting if judgment:

                                
     

    @PostMapping ("/add")

    public String addStudent ( @RequestBody Student student ) {

    if( student == null )

    Return "Student object passed as null, please pass";

    if( student .getName()== null || "". equals(student .getName()) )

    Return "Incoming student name is empty, please pass value";

    if( student .getScore()== null )

    Return "Student grade passed in is null, please pass the value";

    if( (student. getScore()<0 ) || (student .getScore()> 100) )

    The incoming student's score should be between 0 and 100.

    if( student .getMobile()== null || "". equals(student .getMobile()) )

    Return "The incoming student phone number is empty, please send a value";

    if( student .getMobile(). length()! = 11)

    Return "The length of the incoming student's phone number is incorrect. It should be 11 digits."

    studentService .addStudent( student ); // Add student to MySQL database

    return "SUCCESS" ;

    }

Copy the code

This is very tedious!

But with the help of Spring’s annotations, data validation can be very elegant, like this:

                                    
     

    public class Student {

    @notnull (message = "passed name null, please pass value")

    @notempty (message = "name passed as empty string, please pass value")

    private String name; / / name

    @notnull (message = "passed score null, please pass value")

    @min (value = 0,message = "error ")

    @max (value = 100,message = "error ")

    private Integer score; / / score

    @notnull (message = "Incoming phone is null, please pass value")

    @notempty (message = "Incoming phone is empty string, please pass value")

    @length (min = 11, Max = 11, message = "Incoming phone number Length error, must be 11 digits ")

    private String mobile; // Phone number

    }

Copy the code

So a lot of people are asking, how do these annotations work?

Today, this article is the above article @length annotations as an example, to achieve their own, this learned, other annotations are similar to the implementation principle.

There are three big steps.

The first step:
First, define the annotation: @length


     

    @Target({ElementType.FIELD})

    @Retention(RetentionPolicy.RUNTIME)

    public @interface Length {

    int min(); // The minimum allowed string length

    int max(); // Maximum allowed string length

    String errorMsg(); // Custom error message

    }

Copy the code

Here are a few notes:

1. Defining an annotation is a bit like defining an interface, except that it is preceded by an @ sign

2. Annotated member variables can only use primitive, String, or enum enumerations, such as int, but Integer does not

3. The above annotations like @target and @Retention are called “meta annotations”. Meta annotations are specially used to add annotations to annotations

4. @target (XXX) specifies where the custom annotation can be used, for example:

  • Elementtype. FIELD: Indicates that custom annotations can be used for class variables

  • Elementtype. METHOD: Indicates that custom annotations can be used for class methods

  • Elementtype. TYPE: Indicates that custom annotations can be used with the class itself, interface, or enum TYPE

  • And so on… There are many more. If you can’t remember them, I suggest you use them now

5. Use @Retention(XXX) to describe the lifetime of your custom annotations, e.g. :

  • @Retention (retentionPolicy.runtime) : Indicates that annotations are retained until RUNTIME, and therefore can be retrieved through reflection

  • @Retention (retentionPolicy.class) : Indicates that annotations are compiled by the compiler into the CLASS file but ignored at runtime

  • @Retention (retentionPolicy.source) : Indicates that annotations are valid only in the SOURCE file and will be ignored at compile time

In general, if you need to dynamically retrieve annotation information at RUNTIME, use RUNTIME, as in this article.

The second step:
Get the annotations and validate them

What do I do when I want to get the information contained in the annotation generation at run time? That, of course, requires Java reflection knowledge!

Validate () : validate() : validate() : validate() : validate() : validate()


     

    public static String validate( Object object ) throws IllegalAccessException {

    // First get the fields of the class of the object by reflection

    // For this article, we can get Student id, name, mobile

    Field[] fields = object.getClass().getDeclaredFields();

    // The for loop checks field by field to see which field is annotated

    for( Field field : fields ) {

    // check if the field is annotated with @length

    if( field.isAnnotationPresent(Length.class) ) {

    // Get the details of the @length annotation annotated on this field by reflection

    Length length = field.getAnnotation( Length.class );

    field.setAccessible( true ); // Give us access to private variables during reflection

    // Use reflection to get the actual value of the field

    int value =( (String)field.get(object) ).length();

    // Compare the actual value of the field with the value indicated on the annotation

    if( value<length.min() || value>length.max() ) {

    return length.errorMsg();

    }

    }

    }

    return null;

    }

Copy the code

So, how important it is to learn reflection in Java!

Step 3:
Using annotations

This step is easy, and the process of using annotations is often enjoyable


     

    public class Student {

    private Long id; / / student id

    private String name; / / name

    @length (min = 11, Max = 11, errorMsg = "Phone number must be 11 digits long ")

    private String mobile; // Mobile phone number (11 digits)

    }

Copy the code

How, in fact, it is not complicated, mainly reflection related knowledge!

Well, that’s all for your hands-on tips on customizing annotations. Make a little progress every day, Peace!

2020.02.24 late

Give a [Looking at the] is the biggest support for program sheep

Copy the code