Hello, everyone, I am the public number: [Java xiaojie want to fuel], recently in the project, found a lot of places are used to custom annotations, according to the custom annotations, and then to do some personalized operations, very convenient, today to share with you

  • Don’t say a word. Just drive

Notes overview

First, let’s declare an annotation


// Where can annotations be used
@Target({ElementType.TYPE})
// The annotation's life cycle
@Retention(RetentionPolicy.RUNTIME)
// indicates that by default, comments with type will be logged by Javadoc * and similar tools
@Documented
// Can inherit superclass annotations
@Inherited   
// bean
@Component
public @interface DIYClassAnnotation {
    DIYEnum diyEnum(a);
    // The default age is 24
    int age(a) default 24;

}
Copy the code

Notice that this annotation that we declare, he himself carries a lot of meta-annotations, so let’s interpret it accordingly, and the corresponding desirable values are as follows

  • @Target: refers to where this annotation can be marked, is the field? Or class? Or method?
    • TYPE: class, interface (including annotation TYPE), or enumeration declaration
    • FIELD: FIELD declaration (including enumeration constants)
    • METHOD: indicates the METHOD declaration
    • PARAMETER: formal PARAMETER declaration
    • CONSTRUCTOR: CONSTRUCTOR declaration
    • LOCAL_VARIABLE: local variable declaration
    • ANNOTATION_TYPE: Annotation type declaration
    • PACKAGE: PACKAGE declaration
    • TYPE_PARAMETER: type parameter declaration
    • TYPE_USE: indicates the usage type
  • @Retention: refers to the life cycle of the annotation, at which stage it exists
    • SOURCE: Comments will be discarded by the compiler
    • CLASS: Comments are recorded in CLASS files by the compiler, but need not be retained by the VM at run time. This is the default behavior.
    • RUNTIME: Comments are recorded by the compiler in class files and held by the VM at RUNTIME * so they can be read reflectively
  • Documented: Indicates that by default, annotations with types will be Documented by Javadoc * and similar tools
  • @Inherited: Inherited annotations can be Inherited
  • The values inside can only be annotated with the basic types Boolean, int, double, float, long, byte, short, char, String, Enum, Class, and a few other annotations

When we usually write notes. Use the properties and values highlighted above

We practice

  • In fact, with this custom annotation, a thousand words are one sentence
  1. Start by declaring a custom annotation
  2. Take out this annotation through reflection and so on, and then do some custom operations based on the values set in the annotation
  • This article will demonstrate the use of three types of custom annotations, which are the only types of common development (I’ve touched on them)

Custom class annotations

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Component
public @interface DIYClassAnnotation {
    // Custom enumerated types
    DIYEnum diyEnum(a);
    // The default age is 24
    int age(a) default 24;
}
Copy the code

Take a look at this enumerated type


public enum DIYEnum {
    xiaoJie("Xiao jie"."Code"),
    TEACHER("Teacher"."Teaching"),
    CHEF("Chef"."Cook");

    private String name;
    private String worker;

    DIYEnum(String name,String worker) {
        this.name = name;
        this.worker = worker;
    }

    public String getWorker(a) {
        return worker;
    }

    public void setWorker(String worker) {
        this.worker = worker;
    }

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name; }}Copy the code

Custom field annotations


// Where is the annotation to the attribute
@Target({ElementType.FIELD})
// The annotation's life cycle
@Retention(RetentionPolicy.RUNTIME)
// indicates that by default, comments with type will be logged by Javadoc * and similar tools
@Documented
// Can inherit superclass annotations
@Inherited
// bean
@Component
public @interface DIYFieldAnnotation {
    / / gender
    String sex(a);

}

Copy the code

3. Custom method annotations


// Where is the annotation to the method
@Target({ElementType.METHOD})
// The annotation's life cycle
@Retention(RetentionPolicy.RUNTIME)
// indicates that by default, comments with type will be logged by Javadoc * and similar tools
@Documented
// Can inherit superclass annotations
@Inherited
// bean
@Component
public @interface DIYMethodAnnotation {
    // Whether to check
    int verification(a);

    // Interface name
    String interfaceName(a);
}

Copy the code
  • In fact, we noticed that it felt like everyone was very different. Yes, it was just that the target scope was different

Now that we’ve defined our custom annotations, it’s time to actually use them

  • Define an abstract parent class Person
// Abstract superclass
public abstract class Person {
  public  abstract void hobby(a);
}

Copy the code
  • Define Student subclasses
@DIYClassAnnotation(diyEnum = DIYEnum.xiaoJie,age=23 )
public class Student extends Person {

    @diyfieldannotation (sex = "male ")
    private String sex;

    @Override
    public void hobby(a) { System.out.println(DIYEnum.xiaoJie.getWorker()); }}Copy the code
  • Define a Teacher subclass
@DIYClassAnnotation(diyEnum = DIYEnum.TEACHER,age=46 )
public class Teacher extends Person {

    @diyfieldannotation (sex = "female ")
    private String sex;

    @Override
    public void hobby(a) { System.out.println(DIYEnum.TEACHER.getWorker()); }}Copy the code
  • Define the Chef Chef subclass
@DIYClassAnnotation(diyEnum = DIYEnum.CHEF,age=50 )
public class Chef extends Person {

    @diyfieldannotation (sex = "male ")
    private String sex;


    @Override
    public void hobby(a) { System.out.println(DIYEnum.CHEF.getWorker()); }}Copy the code

One more annotation utility class



public class DIYAnnotationUtils {
    public static Person getPerson(Person ... persons){

        for (Person person:persons) {
            // Determine if the class has this annotation
            if (person.getClass().isAnnotationPresent(DIYClassAnnotation.class)){
                // Get this custom annotation
                DIYClassAnnotation workerAnnotation = person.getClass().getAnnotation(DIYClassAnnotation.class);
                // Determine if the value of the custom annotation is what we want
                if (DIYEnum.xiaoJie.getName().equals(workerAnnotation.diyEnum().getName())){
                    // Reflection gets the properties of this object
                    Field[] fields = person.getClass().getDeclaredFields();
                    for (Field field:fields) {
                        // If the field has this annotation
                        if (field.isAnnotationPresent(DIYFieldAnnotation.class)){
                            // Print out the value of the annotation on the propertyDIYFieldAnnotation annotation = field.getAnnotation(DIYFieldAnnotation.class); System.out.println(annotation.sex()); }}returnperson; }}}return null; }}Copy the code

The main one is this utility class (using reflection), which determines whether the object passed in meets our requirements (annotation name is not small Jay), if so, annotation annotation on the property of the annotation out

  • Let’s call it from our visual class

public class Test {
    public static void main(String[] args) {
        Student student =new Student();
        Chef chef = new Chef() ;
        Teacher teacher = new Teacher();
        Person person = DIYAnnotationUtils.getPerson(student, chef, teacher);
        if(person ! =null){ person.hobby(); }}}Copy the code

The output is

Men play codeCopy the code
  • Let’s demonstrate how to use annotations in methods. The most common combination is custom annotations plus AOP

Now let’s look at controller


@RestController
public class Controller {
     // This method requires validation
     @diymethodannotation (verification = 1,interfaceName = "student hobby interface ")
     @RequestMapping("/verification")
     public   String   verificationMethod(String id){
         new Student().hobby();
         return "Check";
    }

    // This method does not require validation
    @diymethodannotation (verification = 0,interfaceName = "teacher hobby interface ")
    @RequestMapping("/noVerification")
    public   String   noVerificationMethod(String id){
        new Teacher().hobby();

        return "Non-check";
    }

    // This method has no annotations
    @RequestMapping("/noAnnotation")
    public   String   noAnnotationMethod(String id){
        new Chef().hobby();

        return "No notes."; }}Copy the code

This article focuses on annotations. This section class has many refinements but is outside the scope of this article


@Component
@Aspect
public class LogAspect {
    // The position of the annotation
    @Pointcut("@annotation(com.example.demo.annotation.DIYMethodAnnotation)")
    public void diyPointCut(a){};

    @Around("diyPointCut()")
    public Object diyAround(ProceedingJoinPoint joinPoint){
        // Get information about the enhanced method
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        // Get the method
        Method method = signature.getMethod();
        // Get the annotation above this method
        DIYMethodAnnotation diyMethodAnnotation = method.getAnnotation(DIYMethodAnnotation.class);
        // Perform custom operations based on attributes defined by annotations
        if (diyMethodAnnotation.verification() == 1){
            System.out.println("The current check is:"+diyMethodAnnotation.interfaceName());
            System.out.println("Method name is:"+method.getName());
            System.out.println("The transfer parameter is:"+JSON.toJSONString(joinPoint.getArgs()));
        }

        System.out.println("Aop interceptor verification:"+diyMethodAnnotation.verification() );


        try {
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null; }}}Copy the code

We run the project through two annotated interfaces

  • Interface to be verified
http://localhost:8081/verification? id=1VerificationMethod (); verificationMethod ();"1"[aop interceptor verification:1A codeCopy the code
  • Interfaces that do not require verification
http://localhost:8081/noVerification?id=1 aop interceptors in verification: 0 to cookCopy the code
  • An interface without annotations
http://localhost:8081/noAnnotation? id=1Cook a mealCopy the code

One conclusion can be drawn from the output,

  • An interface without annotations will not go to AOP, because we AOP configure only annotated interfaces for AOP validation.
  • If there are annotations on the interface, there are two cases (which we set ourselves)
    • verification 0This annotation does not perform any special operations
      • Output “currently validates yes, the method name is, and the pass parameter is
    • This annotation takes special action when verification 1 occurs

In general, if we have special requirements for a class/field/method in daily development, we can use a custom annotation, get the annotation through reflection, and perform our custom operations based on the custom values in the annotation

Good article recommendation

  • How is the network connected from the four – layer model
  • I want to talk to you about operating system memory management
  • I’m confused by the various locks in mysql
  • Five thousand words, yes, we do have an HTTP.
  • The interviewer of JINGdong asked me: “Talk about MySql affairs,MVCC?”

The last

Here’s another quote that’s been trending all over the Internet and touched me a lot

  • God helps those who help themselves

Welcome to pay attention to, I am [Java xiaojie to refueling], what you want to say want to see the welcome comment section, we will see you next time.