每日一例 | 自定义注解简单应用

共 4707字,需浏览 10分钟

 ·

2021-05-23 16:13


经常使用spring相关框架的小伙伴肯定知道什么是注解,而且springboot的配置很多都是通过注解直接注入的,今天我们就来看下如何定义自己的注解,然后通过它实现你自己的业务逻辑。

定义注解

这里简单介绍下,好多小伙伴可能已经忘记了注解方面的知识。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
    public int id();
    public String description() default "no description";
}

@Target@Retention叫元注解,是jdk1.5开始引入的。target的作用是指定可以注解的类型,这里的类型有方法、类、属性等(具体的自己去了解,1.8又增加了新的类型);

Retention的作用是指定注解起作用的时间,有运行时(runtime),编译时(class),源码(SOURCE),只有运行时才会在运行时起作用。

注解是可以定义属性的,当然也可以不定义属性。

定义注解的关键字是@interface

简单应用

我们上面定义的注解是方法级的,所以只能加载方法上,下来我们加在方法上试一下。

public class PasswordUtils {
    @UseCase(id = 47, description = "Passwords must contain at least one numeric")
    public boolean validatePassword(String password) {
        return (password.matches("\\w*\\d\\w*"));
    }
    @UseCase(id = 48)
    public String encryptPassword(String password) {
        return new StringBuilder(password).reverse().toString();
    }
    @UseCase(id = 49, description = "New passwords can't equal previously used ones")
    public boolean checkForNewPassword(List<String> prevPasswords, String password) {
        return !prevPasswords.contains(password);
    }
}

然后编写我们的处理器。注解的处理都是基于反射来实现的,所以这里我们的流程就是先获取目标类的所有方法,接着去获取方法上的注解,如果存在我们加的注解,就进行相应的业务处理。

public class UseCaseTracker {
    public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
        for (Method declaredMethod : cl.getDeclaredMethods()) {
            UseCase uc = declaredMethod.getAnnotation(UseCase.class);
            if (uc != null) {
                System.out.println("Found Use Case:" + uc.id() + " " + uc.description());
                useCases.remove(new Integer(uc.id()));
            }
        }
        for (Integer useCase : useCases) {
            System.out.println("Warning: Missing use case-" + useCase);
        }
    }

    public static void main(String[] args) {
        List<Integer> useCases = new ArrayList<>();
        Collections.addAll(useCases, 47484950);
        trackUseCases(useCases, PasswordUtils.class);
    }
}

加注解的好处特别多,一个特别明显的好处就是可以实现业务解耦。有这样一个场景:你有一个接口的鉴权系统,但你并不是要对所有的业务接口进行鉴权,比如公共接口并不需要登陆,所以并不需要鉴权。如果不用注解的方式,随着系统的不断扩展,需要鉴权的接口越来越多,每次增加新的接口都需要修改配置文件,特别不方便,也繁琐;但如果是通过注解的方式实现的,那就很简单了,你只需要在新接口上增加鉴权注解即可,方便又灵活。突然发现,之前也发过:springboot拦截器解耦——自定义注解

上面说的这个场景也是我之前遇到过的,最终的解决方案就是通过注解方式,在拦截器内部校验注解。另外一个特别常用的应用场景就是实现业务去if-else,特别是对于一些接口系统,二三十个接口,统一入口,需要根据接口请求参数的头部信息,选择调用对于的接口方法,看起来特别不友好:

int serviceNo;
if ("001".equals(serviceNo)) {
    // ...
else if ("002".equals(serviceNo)) {
     // ...
else if ("002".equals(serviceNo)) {
     // ...
}
// ...

如果通过注解的方式,完全就可以干掉if-else了:先扫描你加了注解的接口类,将业务编号与业务处理类建立对应关系(生成一个map),调用对应业务的时候,从map中拿到对应的交易处理类,然后处理并返回。这一块的应用,我前面已经写过了相关的实现方式,感兴趣的小伙伴可以去看看:还在用if-else,新的解耦方式你确定不了解下?

好了,今天就到这里吧!

项目路径:

https://github.com/Syske/example-everyday

本项目会每日更新,让我们一起学习,一起进步,遇见更好的自己,加油呀

- END -


浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报