自定义注解的出路在哪里

一、自定义注解怎么回事?

代码如下(示例):

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
    String Fid();
}

@Target 注解声明注解可使用的范围,如果需要声明多个范围,可以使用{ }括起来
@Retention 中文是保留的意思,和字面意思差不多,就是在程序执行的过程中,保留的位置RetentionPolicy保留策略,大家在使用的时候会发现有三个值,CLASS,SOURCE,RUNTIME,具体是在编译时候保留存在,在CLASS文件中存在,在JVM运行时还存在。这个一般都会使用RUNTIME,你也不想让你的注解夭折吧
@Documented 这注解存在感很低,会生成java doc文档注释,不知道这个具体用法…

OK 这样你就自定义了一个注解,但是这样有啥用,随便去标记一下嘛,那岂不是很傻叉,还有里面的这个String Fid(),写着干嘛?

二、使用这个注解

1.作用情况

代码如下(示例):

    @ResponseBody
   	@GetMapping(value ="/test")
    @MyAnnotation(Fid = “test”)
    public User getUserData(@RequestBody User user){
        System.out.println(user.getUname());
        return userService.getUserById(user.getId());
    }

这里我在想,我自己写了个注解(还不错哦),但是说实话,这个注解在给我提示说(有那个大病),你要说他有什么作用,就是刚刚那个Fid 字段告诉我,这是个test,其实这个自定义的字段不写也是没有什么问题的。
如果就这样去使用了这个注解,那确实有点浪费了,要具体了解他如何使用,这时候就要了解到我们的Aop了,既然这个注解在之前说到是作用在方法上,那我们在方法上加了这个注解之后不就是可以通过Aop来对这个操作了。

    //切点
  @Pointcut("execution(* com.lwy.madmod.learn.service.UserServiceImp.*(Integer))")
  public void pointCut(){}
  @Pointcut("@annotation(MyAnnotation)")
  public void anpCut(){}

关于execution表达式这个在这里大家应该不陌生了,这里提一下**"@annotation(MyAnnotation)",他是我们通过切入该注解作用方法的,在 @annotation() 里面我们写的也是该注解的位置,只不过企业里面一般是把自定义的注解和对应的切面**写在同一个包的文件下面,可以直接找到。

2.搭配切面具体使用

代码如下(示例):maven依赖,springboot下只需要下面这个就行,如果是spring的话,可以看spring下的相关依赖,切记。
第一个依赖只是提供了@Before、@Aspect等注解使用,但是不会生成代理织入,这样是没有效果的。

        <dependency>
            <groupId>repository.org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.6</version>
        </dependency>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

使用@Aspect注解定义之后,通过@Component加入道IOC容器里面,SpringBoot下会自动扫描配置,不用担心


@Aspect
@Component
public class AspectDemo {

    //切点
    @Pointcut("execution(* com.lwy.madmod.learn.service.UserServiceImp.*(Integer))")
    public void pointCut(){}
    @Pointcut("@annotation(MyAnnotation)")
    public void anpCut(){}

    @Before("pointCut()")
    public void toBefore(){
        System.out.println("This is a before cut");
    }

    @Around("anpCut()")
    public Object toAround(ProceedingJoinPoint joinPoint) throws Exception {
        Object[] args = joinPoint.getArgs();
        Class<?> aClass = args[0].getClass();
        Field ids = aClass.getDeclaredField("id");
        ids.setAccessible(true);
        System.out.println(ids.get(args[0]));
        User usr = new User(2,"2","123");
        args[0] = usr;
        Object proceed = null;
        try {
             proceed = joinPoint.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }

附上一张从大佬哪里搞过来的图,哈哈哈具体可以看大佬在这里插入图片描述
具体的处理,我这里讲一下 @Around 这个很厉害的东西
ProceedingJoinPoint joinPoint是得到连接点的对象,我们通过@Around一般是在方法放行前做一定的校验
这其中可以通过反射得到具体的对象的类型,对刚刚的String Fid 那个字段还有印象嘛,我们可以通过规定方法上的Fid值去做对应的校验,每个Fid对应能够告诉我们这个方法对应什么,不然出现了多个同一注解,不好区分。继续说一下@Around,如果我们不执行joinPoint.proceed(),这个方法,我们的Aop是不会放行的,这个时候程序也还没有走完,既然他还可以控制放行,我们是不是还有想法?那就是他也可以改变我们的传入进来的值,上面一个是我使用new 对象的方式去改值的。

 @Around("anpCut()")
    public Object toAround(ProceedingJoinPoint joinPoint) throws Exception {
        Object[] args = joinPoint.getArgs();
        Class<?> aClass = args[0].getClass();
        Field ids = aClass.getDeclaredField("id");
        ids.setAccessible(true);
        ids.set(args[0],2);
        Object proceed = null;
        try {
             proceed = joinPoint.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }

建议使用第二种,Tips:就是我们在joinPoint.proceed(args),这个args是一个Object集合,对应里面的Object一定要和你前端接口传入的是一样的类型。

@ResponseBody
    @GetMapping(value ="/test")
    @MyAnnotation()
    public User getUserData(@RequestBody User user){
        System.out.println(user.getUname());
        return userService.getUserById(user.getId());
    }

不然会报转化异常的。

总结

要把反射注解和框架里面的知识联系起来使用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值