Spring 自定义注解

  • 目录

1. 前言

  • 注解为我们提供了形形色色的功能,依赖注入,记录日志,自动创建setter,getter方法等等。但究竟什么是注解?这些功能是怎么实现的?在开发中我们有没有需求需要用到自定义注解来实现自己的功能?如果有,我们要怎么创建我们自己的注解?
2. 注解的原理
  • 注解本质是一个继承了Annotation 的特殊接口,其具体实现类是Java运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler 的invoke 方法。该方法会从memberValues 这个Map 中索引出对应的值。而memberValues 的来源是Java常量池。

3. 创建自定义注解

  1. 创建@Spongebob 自定义注解
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD,ElementType.FIELD})
@Inherited
public @interface Spongebob {
	String value() default "假装说点什么...";
}
  • 注解的类型为@interface,所有的Annotation 会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口。
  • 我们看到我在Spongebob 注解上还加了4个注解,这四个注解比较特殊叫元注解
3.1 元注解

元注解就是可以加在注解上的注解,元注解不可以自定义。下面我来一一说明一下这四个元注解的作用。

@Documented

如果添加了@Documented,注解将能够在JavaDoc中展现。

@Retention

描述注解的生命周期,即什么时候注解是有效

类型 说明
RetentionPolicy.SOURCE 在源文件中有效
RetentionPolicy.CLASS 在 class 文件中有效
RetentionPolicy.RUNTIME 在运行时有效
@Inherited

是否允许子类继承该注解。即@Spongebob 如果修饰了类A,那么类A的子类类B也会默认被@Spongebob 修饰。

@Target

表示该注解用于什么地方。默认值为任何元素,表示该注解可以用于任何地方。注解值可以多选,如果建注解用到了未定义的地方,编译会报错。

类型 说明
CONSTRUCTOR 可用于描述构造器
FIELD 用于描述域(属性)
LOCAL_VARIABLE 用于描述局部变量
METHOD 用于描述方法
PACKAGE 用于描述包
PARAMETER 用于描述参数
TYPE 用于描述类或接口(甚至 enum )

  • 这四个元注解都是可选的,不一定需要添加
  • 接着我们看到我给@Spongebob 添加了一个参数value,并设置了默认值。关于参数也有一些要求。
3.2 注解参数
  1. 参数成员只能用public 或默认(default) 这两个访问权修饰
  2. 参数成员只能用基本类型byte、short、char、int、long、float、double、boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这些类型的数组类型.
  3. 可以为参数设置默认值
  4. 如果注解只有一个参数,在使用时可以直接去掉参数名赋值
@Spongebob("你说我好看")
  1. 如果注解有多个参数,必须通过名称赋值,并以‘,’分割
@Spongebob(value="你说我好看",xx="xxx")
  1. 如果参数类型是数组类型,使用方法
@Spongebob({"你说我好看",“却是吃了吐”})
  1. 如果参数类型是数组类型,但是只有一个数据,可以去掉大括号赋值
@Spongebob("快乐都是他们的”)

  • 如果想要获取到解信息,必须通过反射机制,通过反射获取被修饰的类或方法对象,便可以获取到修饰的注解对象信息。
4. 使用@Spongebob注解
@RestController
@RequestMapping("/index")
public class IndexController {

    @Autowired
    LoginService loginService;

    @Spongebob
    @RequestMapping("/testAnnotation")
    public String testAnnotation(String name,String password){
        String info= loginService.login(name,password);
        System.out.println(info);
        return info;
    }

这里的@Spongebob没有任何实际的功能,我这里加个@Spongebob注解是为了表达这个testAnnotation方法是名为Spongebob的人开发的。

这里我们可以看出注解最原始的用处就是一个标签,为方法加一个标签,为类加一个标签,为字段属性加一个标签,表明这个方法或这个类有特殊含义。


  • 这一章是对自定义注解的简单介绍,下一章我们将介绍自定义注解的进阶使用——自定义注解的切面编程。
  • 下一章:自定义的注解的切面编程

你可能感兴趣的:(annotation,spring)