0.定义

注解是一种能被添加到java源代码中的元数据,方法、类、参数和包都可以用注解来修饰。注解可以看作是一种特殊的标记,可以用在方法、类、参数和包上,程序在编译或者运行时可以检测到这些标记而进行一些特殊的处理。

(1)创建一个注解的基本元素

修饰符
访问修饰符必须为public,不写默认为pubic;
关键字
关键字为@interface;
注解名称
注解名称为自定义注解的名称,例如上面的XinLinLog 就是注解名称
注解类型元素
注解类型元素是注解中内容,根据需要标志参数,例如上面的注解的value;

(2)元注解(@Target、@Retention、@Inherited、@Documented)

我们上面的创建的注解XinLinLog上面还有几个注解(@Target、@Retention、@Inherited、@Documented),这四个注解就是元注解,元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的元注解类型,它们被用来提供对其它 注解类型作标志操作(可以理解为最小的注解,基础注解)

@Target:用于描述注解的使用范围,该注解可以使用在什么地方

类型描述
ElementType.TYPE应用于类、接口(包括注解类型)、枚举
ElementType.FIELD应用于属性(包括枚举中的常量)
ElementType.METHOD应用于方法
ElementType.PARAMETER应用于方法的形参
ElementType.CONSTRUCTOR应用于构造函数
ElementType.LOCAL_VARIABLE应用于局部变量
ElementType.ANNOTATION_TYPE应用于注解类型
ElementType.PACKAGE应用于包

@Retention:表明该注解的生命周期

生命周期类型描述
RetentionPolicy.SOURCE编译时被丢弃,不包含在类文件中
RetentionPolicy.CLASSJVM加载时被丢弃,包含在类文件中,默认值
RetentionPolicy.RUNTIME加载,包含在类文件中,在运行时可以被获取到

@Inherited:是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

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

1.常见自定义注解

上面总结的注解的定义,但是创建这样一个注解,仅仅是一个标志,装饰类、方法、属性的,并没有功能,要想实现功能,需要我们通过拦截器、AOP切面这些地方获取注解标志,然后实现我们的功能。

注意:后面介绍的很多注解有第三方框架已经实现了,如果不想自定义可以直接使用第三方框架,如果第三方框架不能满足自己项目的需求,则可以考虑自定义框架。

(1)身份验证注解

有的时候我们访问后台接口的时候,存在一个简单逻辑:有的接口用户没有登录的情况下是不允许访问的。比如获取用户数据的一个接口,如果用户根本没有登录,那么当前这个接口是根本不能访问的。有的接口用户不登录也要允许获取数据,比如验证码。

shiro框架中的@RequiresAuthentication 注解就可以简单实现这个功能。

(2)角色权限注解

除了上面判断当前这个接口是否需要登录才能访问,有的接口还需要判断哪些角色才有权限来访问。比如用的接口只允许管理员访问,而有的接口只允许某个角色来访问(比如’学生’,’老师’等)。

shiro框架中的@RequiresRoles注解就可以简单实现实现这个功能。比如下面这样:

    @RequiresRoles(value = {"root","admin"})

(3)字段属性注入注解

字段属性注入就是在实例化对象时,同时向对象中的属性进行相应的赋值。
即,通俗点说,字段属性注入就是给类中的属性赋值。

(4)对象的属性校验注解

这个功能主要用来校验对象的某些属性是否符合要求,比如是否为空,手机号码是否符合要求等。

validation这个包中@Valid注解就具备这个功能。

@Valid注解基础用法如下:

public class User{
    @NotBlank(message = "姓名不为空")
    private String username;
    @NotBlank(message = "密码不为空")
    private String password;
}

如果嵌套的实体对象,则需要在最外层属性上添加@Valid注解

public class User{
    @NotBlank(message = "姓名不为空")
    private String username;
    @NotBlank(message = "密码不为空")
    private String password;
    //嵌套必须加@Valid,否则嵌套中的验证不生效
    @Valid
    @NotNull(message = "用户信息不能为空")
    private UserInfo userInfo;
}

如果觉得上面的功能不够用,也可以自定义对象的属性校验注解。

(5)操作日志注解

这个注解可能是自定义最多的,有时候我们访问接口时,需要记录下用的用户名、操作的接口、提交的参数、操作的内容、隶属模块、操作时间等等。虽然现在的已经有很多第三方日志框架了,但是因为每个项目的内容不同,需要记录的操作日志也不同,所以很多项目需要自定义操作日志注解。

(6)缓存注解

使用这个注解的场景是:有的时候我们需要往缓存中存取数据,这个逻辑是如果缓存中如果有这个数据了,那么就直接取,如果没有这个数据,那么就直接存进去。

spring当中里面已经有一个@Cacheable注解,已经实现了此功能,如果觉得不够用可以自定义这个注解。

类似的跟缓存有关的注解还有@CachePut、@CacheEvict、@CacheConfig、@Caching等

(7)防刷注解

也是比较常用的注解,有些人总会去无限次的请求接口,比如暴力测试登录接口,这时候就有必要在这个接口上加一些限制,比如1秒至多请求三次等,限制某IP提交等。

(8)动态切换数据源注解

有的项目有多个数据源,不同的接口可能要从不同的数据库存取数据,这个时候我们可以通过自定义注解实现访问不同的数据源。