Spring自定义注解
内容纲要

Spring注解

初学spring的时候使用注解总觉得使用注解很神奇,加一个注解就能实现想要的功能,很好奇,也想自己根据需要写一些自己实现的自定义注解。问题来了,自定义注解到底是什么?

查阅资料后发现,注解就是一种标志,单独使用注解,就相当于在类、方法、参数和包上加上一个装饰,什么功能也没有,仅仅是一个标志。这个标志可以加上一些自己定义的参数。

但是可以通过AOP、拦截器等识别出注解标记的类或方法,然后实现相应的增加功能。

创建一个注解的基本元素

  • 修饰符:必须为public,默认也为public
  • 关键字:@interface
  • 注解名称:自定义注解的名称
  • 注解类型元素:可以比作是在方法或类上标记注解时传递的参数。

元注解

  • @Target:描述注解适用的范围

    • ElementType.TYPE 应用于类、接口(包括注解类型)、枚举
    • ElementType.FIELD 应用于属性(包括枚举中的常量)
    • ElementType.METHOD 应用于方法
    • ElementType.PARAMETER 应用于方法的形参
    • ElementType.CONSTRUCTOR 应用于构造函数
    • ElementType.LOCAL_VARIABLE 应用于局部变量
    • ElementType.ANNOTATION_TYPE 应用于注解类型
    • ElementType.PACKAGE 应用于包
  • @Retention:表明注解的生命周期

    • RetentionPolicy.SOURCE 编译时被丢弃,不包含在类文件中
      RetentionPolicy.CLASS JVM加载时被丢弃,包含在类文件中,默认值
      RetentionPolicy.RUNTIME 由JVM 加载,包含在类文件中,在运行时可以被获取到
  • @Inherited:@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

  • @Documented:表明该注解标记的元素可以被Javadoc 或类似的工具文档化

自定义注解用法

依赖于@Conditional

原理是是否满足@Conditional中绑定类的条件,如果满足,就将使用注解的类注入进factory,不满足就不注入,只能在类中使用或者配合@bean使用

// 查找有标有注解的类
DynamicTp dynamicTp = beanFactory.findAnnotationOnBean(beanName, DynamicTp.class);

配合AOP使用

将注解作为切入点,执行AOP的增加功能。

在spring中可以使用 class.isAnnotationPresent 或者 class.getAnnotation 获取类的注解,但是使用AOP代理了这个类后你会发现获取不到注解了。

拿不到自定义注解

补充:其实这样做根本不是拿方法的注解,拿的是 joinPoint.getTarget().getClass()的注解

// 所切对象的类
Class<?> aClass = joinPoint.getTarget().getClass();
log.info("目标对象:[{}]--[{}]",aClass,aClass.getName());
// 所切方法名
String methodName = joinPoint.getSignature().getName();
log.info("所切方法名:[{}]",methodName);
StringBuilder sb = new StringBuilder();
// 所切方法参数
Object[] args = joinPoint.getArgs();
for(Object arg:args){
    sb.append(arg);
}
log.info("所切方法的传入参数列表:[{}]",sb.toString());
Annotation[] annotations = aClass.getAnnotations();
for(Annotation a:annotations){
    log.info("所切方法上的注解:[{}]    type:[{}]",a,a.annotationType());
}
Signature signature = joinPoint.getSignature();
MyAnnotation annotation = signature.getClass().getAnnotation(MyAnnotation.class);
String args1 = annotation.args();
int num = annotation.num();
log.info("注解MyAnnotation的参数:[{}] [{}]",args1,num);

能拿到注解的方法

上面的方法拿不到注解是因为,直接通过signture拿到的是代理的方法,而代理的方法是不会加上原方法的注解的。

只有拿到原始的方法才能拿到注解的值。

Signature signature = joinPoint.getSignature(); // 方法签名
Method method = ((MethodSignature) signature).getMethod();
Method realMethod = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), method.getParameterTypes());
MyAnnotation annotation = realMethod.getAnnotation(MyAnnotation.class);
//     MyAnnotation annotation = joinPoint.getTarget().getClass().getAnnotation(MyAnnotation.class);
//     MyAnnotation annotation = signature.getClass().getAnnotation(MyAnnotation.class);
String args1 = annotation.args();
int num = annotation.num();
log.info("注解MyAnnotation的参数:[{}] [{}]",args1,num);

配合拦截器使用

通过注解决定是否拦截

可以通过检查方法关于注解的信息来决定拦截结果,例如可以根据有无注解拦截或者根据注解的参数决定是否拦截。

以下Demo就是通过判断开发者打上注解时是否添加 authorities = {"admin"} 判断是否要拦截。

// Controller:
    @PostMapping("/t")
    @InterceptorAnnotation(authorities = {"admin","role"})
    public void isAdmin(){
        log.info("Controller 执行结束");
    }

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    log.info("===== PreHandler开始");
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    Method method = handlerMethod.getMethod();
    InterceptorAnnotation annotation = method.getAnnotation(InterceptorAnnotation.class);
    if(annotation == null){
        log.info("该方法没有打上InterceptorAnnotation注解");
        return true;
    }
    log.info("该方法打上InterceptorAnnotation注解");
    String[] authorities = null;
    if(annotation.authorities().length > 0){
        authorities = annotation.authorities();
        for(String auth:authorities){
            if(auth.equals("admin")){
                log.info("该用户是admin");
                log.info("===== prehandler结束");
                return true;
            }
        }
    }
    if(authorities == null){
        log.info("注解上没有注明用户身份");
        return false;
    }
    log.info("该用户是:[{}]",authorities[0]);
    log.info("该用户不是admin");
    log.info("===== prehandler结束");
    return false;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇