【Java基础】如何自定义注解

一、注解的作用

java的反射技术很强大,可以在程序运行时动态获取类信息、字段、方法等,再执行各种想要的操作。

但是,有时我们还希望对一些信息提前描述,以便在使用反射时,区别性地进行处理,使得处理更加灵活,这时候就需要用到注解了。

二、如何自定义注解

  1. 语法: 修饰符 + @interface +注解名
  2. 成员变量的类型会有限制,仅限以下:基本数据类型、String、Class、enum、Annotation 以及它们对应的数组。
  3. 需要4个元注解,分别是
    @Target —— 指定此注解使用的对象,包括类、字段、方法等
    @Retention —— 指定保存的周期,包括源代码、运行时等
    @Documented —— 此注解可用于javadoc生成文档
    @Inherited —— 解释挺拗口,个人理解是,带有这个元注解的注解,它的属性很“霸道”,不仅修饰直接修饰的类,还会修饰它的子类
    上面三个注解比较好理解,就最后一个不太懂,因此用了一个例子执行了一下。
	// 自定义注解
	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	@Inherited
	@Documented
	public @interface MyClassAnno {
	    String name() default "";
	}
	
	// 被自定义注解修饰的类
	@MyClassAnno
	public class BeAnnoed {
	}
	
	// 继承被注解修饰的类
	public class BeAnnoedSon extends BeAnnoed{
	}

	// 测试类
	public class Client {

    public static void main(String[] args) {
        Annotation[] annotations = BeAnnoedSon.class.getAnnotations();
        for(Annotation annotation: annotations){
            System.out.println("BeAnnoedSon注解为:"+annotation.annotationType());
        }
    }
}

当不使用@Inherited时, 结果毛都没有
在这里插入图片描述

当自定义注解使用@Inherited修饰,可以看到,子类已经被自定义注解修饰。因为子类有这个注解,所以子类的子类也会被此注解修饰,“子子孙孙无穷匮也”
在这里插入图片描述

三、 使用场景

如果注解没有成员变量,作用会相对比较局限,只能用来做标记。但如果加上成员变量,我们可以做更多的事情。比如可以自定义日志注解,配合切面,这样就可以在任何想要加日志处理的地方,灵活地配合注解参数,进行处理。
(偷个懒,以下代码摘自某开源项目,不得不感叹一句,人家写的代码就是好看呀)

1.先自定义一个日志注解

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
    /**
     * 模块 
     */
    public String title() default "";

    /**
     * 功能
     */
    public BusinessType businessType() default BusinessType.OTHER;

    /**
     * 操作人类别
     */
    public OperatorType operatorType() default OperatorType.MANAGE;

    /**
     * 是否保存请求的参数
     */
    public boolean isSaveRequestData() default true;
}

2.比如在一个保存字典值的方法处记录日志

@Log(title = "字典数据", businessType = BusinessType.INSERT)
    @RequiresPermissions("system:dict:add")
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(@Validated SysDictData dict)
    {

3.编写切面类

	// 配置织入点
    @Pointcut("@annotation(com.**.common.annotation.Log)")
    public void logPointCut()
    {
    }

	// 比如记录成功的日志
  	@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
    {
        handleLog(joinPoint, null, jsonResult);
    }
	
	// handleLog中通过切点,获取注解
	 protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
    {
        try
        {
            // 获得注解
            Log controllerLog = getAnnotationLog(joinPoint);
		}
	}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值