理解java注解二

前面写了理解java注解一,但是我估计大家都不会太在意:不就是一些注解的概念之类的吗?不过,我还是觉得,基础很重要。我刚开始了解注解的时候,就很纳闷:一个注解,写个名字,代码就知道自己要干啥?你当这是人工智能啊!然后问其他小伙伴,他们也是一知半解,茫茫然然。后来去看注解讲解,慢慢猜明白了一些。

一个注解,看起来高大上,可以进行参数校验,数据转换,方法处理的过滤处理等等等等,实际上,不过是通过反射,在后台默默实现一遍罢了,这些代码才真是逻辑处理的无名英雄!

若果大家使用过java框架一段时间,都会或多或少的接触使用注解,对一些注解的作用也是耳熟能详。可能更多的人都是使用Spring全家桶,@RestController,@ResponseBody,@RequestBody,@Autowired,@Resource,@RequestParam,@Service,@Component,@Repository,@Mapper,@Configuration,都非常熟悉,用起来也很方便。

不过其中的原理都不甚了解,甚至一点开这些注解,可能都是一大坨,懒得去看,这些东西贸然去看,确实很头疼,我也没能力把这些讲清楚,我今天就讲个入门,后续大家有兴趣的话可以看下Spring源码深度解析,了解这些注解的实现。

这里我提一句哈,一些新手可能会犯这样的错误。

@RestController("/demo")
public class DemoController {

    @PostMapping("test")
    public DefaultResponse getInfoList(@RequestBody RequestVo requestVo){
        return  null;
    }
}
@Data
public class RequestVo {

    private  String uuid ;

    private Integer minAge;

    private String maxAge;

    // 学校id必须不为空

    @NotNull(message = "学校id不能为空")
    private String schoolId;

}

大家可以看到,这是一个简单的不能再简单的一个Spring的请求接收处理,通过@RequestBody 直接将json入参转换为对象RequestVo ,同时添加了校验schoolId 不能为空。

当然,细心的小伙伴已经发现,其实这个校验  @NotNull(message = "学校id不能为空")  并不能起作用,原因很简单,之前就说了,注解不是人工智能,不可能自己识别的,而且这个@NotNull 并没有和@RequestBody 并没有结合到一起,也没有直接嵌入到Spring里面,根本就不可能自动校验。不知道有没有小伙伴遇到这样的问题,测试提bug的时候还很纳闷,不过这种不仔细测试还真不好发现,哈哈,调节下气氛。

其实,打开这个@NotNull 就可以发现,它的使用是和另一个注解结合的,那就是@Valid,只有这样写,才真正的做了为空校验

   @PostMapping("test")
    public DefaultResponse getInfoList(@Valid @RequestBody RequestVo requestVo){
        return  null;
    }

当然,这个@Valid封装的很经典,同一个接口多次请求的话,可以根据需要,进行不同的过滤规则,这个大伙有兴趣的可以看下哈~(主要就在@NotNull 中的groups定义处理)

扯得有点远了,开始正题。

下面写一个简单的注解获取。

注解颜色:

package com.example.annotion;

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Color {
    String value();
}

这是一个很普通的注解,就是颜色,value 表明颜色的值

水果Apple ,水果自然是有颜色的,比如,你听到苹果,可能就能知道,哦,颜色是红色:

package com.example.vo;

import com.example.annotion.Color;
import lombok.Data;

@Data
public class Apple {

    @Color(value = "red")
    private String name;

    private Double price;

}

注解的获取:

package com.example.demo;

import com.example.annotion.Color;
import com.example.vo.Apple;

import java.lang.reflect.Field;

public class MyTest {
    public static void main(String[] args) throws Exception{

        // 加载类
        Class<?> appleClass = Class.forName("com.example.vo.Apple");
       //这样也可以  Class<? extends Apple> appleClass = new Apple().getClass();
        Field[] fields = appleClass.getDeclaredFields();
        for (Field field:fields) {
            field.setAccessible(true);
            Color color = field.getAnnotation(Color.class);
            if (color != null){  // 说明有Color 的注解
                System.out.println("apple 的颜色是:" + color.value());
                System.out.println(" 属性的名称是: " + field.getName());
            }
            break;
        }
        System.out.println("this is end.....");
    }
}

输出结果:

Connected to the target VM, address: '127.0.0.1:58458', transport: 'socket'
apple 的颜色是:red
 属性的名称是: name
this is end.....
Disconnected from the target VM, address: '127.0.0.1:58458', transport: 'socket'

Process finished with exit code 0

当然,大家看到这个例子的时候一定是感觉---垃圾,这么幼稚的获取操作,我也会!

是的,这个注解的解析很基础看,可能稍微学过一点java的人都能写出来。

但是,千遍万变,原理不变,基础这东西,往往很重要,很关键,你不自觉的就容易忽略掉很多。

下面我说一下之前工作中用到的一个注解处理:

一个项目,很多地方都需要文件上传,然后保存文件信息。前端传来一个页面,其中可能有许多需要保存的文件类,比如ImageVo,当然,这个肯定不能一个一个处理,那样太繁琐了,而且这种和业务关系不大的保存操作应该统一封装才最合理。

当然,你每次都取出其中的参数,然后传递到一个方法里也是可以的,但是,你每个请求都要取一遍参数吗?而且如果参数层级比较多呢?还要加判断等等等等,

当然,这个用注解+反射就可以很好的处理!

尽量这周写出来吧,之前太懒了,还是有必要些一些东西沉淀的,O(∩_∩)O哈哈~

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笔下天地宽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值