编程语言
首页 > 编程语言> > 快来自定义一个属于你自己的java注解吧

快来自定义一个属于你自己的java注解吧

作者:互联网

大家好,我是公众号:【java小杰要加油】,最近在项目中,发现了很多地方都用到了自定义注解
根据自定义的注解,再去做一些个性化的操作,非常方便,今天来分享给大家

注解大致介绍

首先,让我们来声明一个注解


// 注解可以作用在哪里
@Target({ElementType.TYPE})
//  该注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
// 指示默认情况下,带有类型的注释将由javadoc *和类似工具来记录
@Documented
// 可以继承父类注解
@Inherited   
// bean
@Component
public @interface DIYClassAnnotation {
    DIYEnum diyEnum();
    // 年龄默认24 岁
    int age() default 24;

}

可以注意到,我们声明的这个注解,他自己又带着很多元注解,我们依此来解释下,对应可取的值也如下

我们一般写注解的时候。就是用图中上面那几个加粗颜色的属性和值

实战演练

  • 其实使用这个自定义注解,千言万语就一句话
  1. 声明一个自定义的注解
  2. 通过反射等方式取出这个注解,再根据这个注解中自己设定的值去做一些定制化的操作

一、自定义类注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Component
public @interface DIYClassAnnotation {
    // 自定义枚举类型
    DIYEnum diyEnum();
    // 年龄默认24 岁
    int age() default 24;
}

看一下这个枚举类型


public enum DIYEnum {
    xiaoJie("小杰","打代码"),
    TEACHER("老师","教书"),
    CHEF("厨师","做饭");

    private String name;
    private String worker;

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

    public String getWorker() {
        return worker;
    }

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

    public String getName() {
        return name;
    }

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


}

二、自定义字段注解


// 注解到什么地方  属性 上
@Target({ElementType.FIELD})
//  该注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
// 指示默认情况下,带有类型的注释将由javadoc *和类似工具来记录
@Documented
// 可以继承父类注解
@Inherited
// bean
@Component
public @interface DIYFieldAnnotation {
    // 性别
    String sex();

}

三、自定义方法注解


// 注解到什么地方  方法 上
@Target({ElementType.METHOD})
//  该注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
// 指示默认情况下,带有类型的注释将由javadoc *和类似工具来记录
@Documented
// 可以继承父类注解
@Inherited
// bean
@Component
public @interface DIYMethodAnnotation {
    // 是否校验
    int verification();

    // 接口名称
    String interfaceName();
}

我们自定义注解定义完了,下面要开始真正使用啦

// 抽象父类
public abstract class Person {
  public  abstract void hobby();
}

@DIYClassAnnotation(diyEnum = DIYEnum.xiaoJie,age=23 )
public class Student extends Person {

    @DIYFieldAnnotation(sex = "男")
    private String sex;

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

    @DIYFieldAnnotation(sex = "女")
    private String sex;

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

    @DIYFieldAnnotation(sex = "男")
    private String sex;


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

再来一个注解工具类



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

        for (Person person:persons) {
            // 判断这个类是否有这个注解
            if (person.getClass().isAnnotationPresent(DIYClassAnnotation.class)){
                // 得到这个自定义的注解
                DIYClassAnnotation workerAnnotation = person.getClass().getAnnotation(DIYClassAnnotation.class);
                // 判断这个自定义注解注解的值是否是我们想要的
                if (DIYEnum.xiaoJie.getName().equals(workerAnnotation.diyEnum().getName())){
                    // 反射得到这个对象的属性
                    Field[] fields = person.getClass().getDeclaredFields();
                    for (Field field:fields) {
                        // 如果这个字段有这个注解
                        if (field.isAnnotationPresent(DIYFieldAnnotation.class)){
                            // 打印出这个属性上有这个注解的值
                            DIYFieldAnnotation annotation = field.getAnnotation(DIYFieldAnnotation.class);
                            System.out.println(annotation.sex());
                        }
                    }
                    return person;
                }
            }
        }
        return null;
    }
}

最主要的就是这个工具类(用到反射),其中根据传进来的对象判断符合不符合我们的要求
(注解时的名字是不是小杰),如果符合的话,把注解在属性上的注解拿出来


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();
        }
    }
}

输出结果是

男
打代码

下面来看下controller


@RestController
public class Controller {
     // 此方法需要校验
     @DIYMethodAnnotation(verification = 1,interfaceName = "学生爱好接口")
     @RequestMapping("/verification")
     public   String   verificationMethod(String id){
         new Student().hobby();
         return "校验";
    }

    // 此方法不需要校验
    @DIYMethodAnnotation(verification = 0,interfaceName = "老师爱好接口")
    @RequestMapping("/noVerification")
    public   String   noVerificationMethod(String id){
        new Teacher().hobby();

        return "不校验";
    }

    // 此方法没有注解
    @RequestMapping("/noAnnotation")
    public   String   noAnnotationMethod(String id){
        new Chef().hobby();

        return "无注解";
    }

}

再看下切面类 本文注重讲解注解,这个切面类还有很多完善的地方不过不在本文范围内


@Component
@Aspect
public class LogAspect {
    // 注解的位置
    @Pointcut("@annotation(com.example.demo.annotation.DIYMethodAnnotation)")
    public void diyPointCut(){};

    @Around("diyPointCut()")
    public Object diyAround(ProceedingJoinPoint joinPoint){
        //获得被增强的方法相关信息
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        // 获得这个方法
        Method method = signature.getMethod();
        // 获得这个方法上面的注解
        DIYMethodAnnotation diyMethodAnnotation = method.getAnnotation(DIYMethodAnnotation.class);
        // 根据注解自定义的一些属性去做自定义的操作
        if (diyMethodAnnotation.verification() == 1){
            System.out.println("当前校验的是:"+diyMethodAnnotation.interfaceName());
            System.out.println("方法名称是:"+method.getName());
            System.out.println("传递参数是:"+JSON.toJSONString(joinPoint.getArgs()));
        }

        System.out.println("aop 拦截器里 verification:"+diyMethodAnnotation.verification() );


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

我们将项目跑起来,分别访问两个打了注解的接口

http://localhost:8081/verification?id=1

当前校验的是:学生爱好接口
方法名称是:verificationMethod
传递参数是:["1"]
aop 拦截器里 verification:1
打代码

http://localhost:8081/noVerification?id=1

aop 拦截器里 verification:0
做饭
http://localhost:8081/noAnnotation?id=1

做饭

由输出结果可以得出一个结论,

综上所述,我们在日常开发中,如果对某个类/字段/方法有什么特殊的要求的话可以使用自定义注解,再通过反射获取到此注解,再根据这个注解中自定义的值在进行我们自定义的操作

好文推荐

原文链接:https://mp.weixin.qq.com/s/IOOmPzmMsdtqqICkkRgEgQ

最后

再贴一张最近火爆全网同时也对我触动很大的话

欢迎大家关注,我是【java小杰要加油】,有什么想说的想看的欢迎评论区里留言,我们下期见。

标签:java,String,自定义,class,verification,注解,public,定义
来源: https://blog.csdn.net/weixin_42659261/article/details/116432475