注解(Annotation),注解是JDK1.5之后才有的新特性,现在很多开发模式都是基于注解驱动的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是基于注解的了,dubbo中也是大量使用注解,spring boot更不用说了,and so on,在咱们项目里也是随处可见的注解,另外项目里也有不少使用自定义注解,所以可见注解的重要性。
JDK1.5之后内部提供的三个注解:
@Deprecated 意思是“废弃的,过时的”
@Override 意思是“重写、覆盖”
@SuppressWarnings 意思是“压缩警告”@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
细心的人都发现了,这三个注解上面都有相同的Target、Retention注解,另外还有一个特别的Documented注解。那么他们又是做什么的呢?
@Target
表示该注解可以用于什么地方,可能的ElementType参数有:CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明
@Retention
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:SOURCE:注解将被编译器丢弃
CLASS:注解在class文件中可用,但会被VM丢弃
RUNTIME:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息。
@Document
将注解包含在Javadoc中
@Inherited
允许子类继承父类中的注解
自定义注解import java.lang.annotation.*;
@Documented
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @ interface MyAnnotation {
}public class User {
//使用自定义的注解
@MyAnnotation
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
把自定义注解MyAnnotation上的注解@Target改成@Target(value = ElementType.TYPE)
则此时User类中就会报错,
正确使用为@MyAnnotation
public class User {
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
如果你想要知道该类上是否存在注解,是否存在自定义的注解,可以通过java的反射机制获取的,然后就可以对拥有该注解的类进行相关的操作。
案列
使用自定义注解来实现:某个接口是否需要验证用登录状态。
登录接口,登录的时候用户肯定还是未登录状态,所以也需要加自定义注解NoCheckLogin。import java.lang.annotation.*;
/**
* @author lawt
* @Description 验证登录接口的注解
* @create 2018/06/08 14:09
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NoCheckLogin {
}/**
* @author tianweichang
* @Description 登录登出操作接口
* @create 2018/06/08 14:16
*/
@RestController
@RequestMapping("/api")
public class LoginController {
//用户登录
@PostMapping(value = "/100001")
@NoCheckLogin
public InterfaceResult toLogin(UserLoginDto userLoginDto){
InterfaceResult result = new InterfaceResult();
logger.info("用户名:【{}】开始登录",userLoginDto.getUserName());
......
}//拦截请求并校验是否需要是登录状态
public class CheckLoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
NoCheckLogin nocCheckLogin =
handlerMethod.getMethodAnnotation(NoCheckLogin.class);
if (nocCheckLogin != null) {
log.info("请求的接口路径:【{}】不需要验证登录", url);
return true;
}
// ......无关代码省略
}
}
后面会把注解相关的完善(注解派生性、常用注解等)。