Java语言注解Annotation与自定义注解详解[Java代码]
龚超 2018-07-18 来源 : 阅读 1473 评论 0

摘要:本文主要向大家介绍了Java语言注解Annotation与自定义注解详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了Java语言注解Annotation与自定义注解详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

一:Java注解简介

开发中经常使用到注解,在项目中也偶尔会见到过自定义注解,今天就来探讨一下这个注解是什么鬼,以及注解的应用场景和如何自定义注解。

下面列举开发中常见的注解

@Override:用于标识该方法继承自超类, 当父类的方法被删除或修改了,编译器会提示错误信息(我们最经常看到的toString()方法上总能看到这货)

@Deprecated:表示该类或者该方法已经不推荐使用,已经过期了,如果用户还是要使用,会生成编译的警告

@SuppressWarnings:用于忽略的编译器警告信息

Junit测试:@Test

Spring的一些注解:@Controller、@RequestMapping、@RequestParam、@ResponseBody、@Service、@Component、@Repository、@Resource、@Autowire

Java验证的注解:@NotNull、@Email

下面看一下注解Override.java的庐山真面目


@Target(ElementType.METHOD)

@Retention(RetentionPolicy.SOURCE)

public @interface Override {


}



复制代码

二:Java注解基本知识

1. Java注解数据类型

注解是写在.java文件中,使用@interface作为关键字, 所以注解也是Java的一种数据类型,从广泛的定义来说,Class、Interface、Enum、Annotation都属于Class类型。

2. Java元注解

在创建注解的时候,需要使用一些注解来描述自己创建的注解,就是写在@interface上面的那些注解,这些注解被称为元注解,如在Override中看到的@Target、@Retention等。下面列出一些元注解

@Documented: 用于标记在生成javadoc时是否将注解包含进去,可以看到这个注解和@Override一样,注解中空空如也,什么东西都没有


@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Documented {


}



复制代码

@Target:用于定义注解可以在什么地方使用,默认可以在任何地方使用,也可以指定使用的范围,开发中将注解用在类上(如@Controller)、字段上(如@Autowire)、方法上(如@RequestMapping)、方法的参数上(如@RequestParam)等比较常见。

TYPE : 类、接口或enum声明
FIELD: 域(属性)声明
METHOD: 方法声明
PARAMETER: 参数声明
CONSTRUCTOR: 构造方法声明
LOCAL_VARIABLE:局部变量声明
ANNOTATION_TYPE:注释类型声明
PACKAGE: 包声明

Target.java


@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Target {

/**

* Returns an array of the kinds of elements an annotation type

* can be applied to.

* @return an array of the kinds of elements an annotation type

* can be applied to

*/

ElementType[] value();

}


复制代码


public enum ElementType {

/** Class, interface (including annotation type), or enum declaration */

TYPE,


/** Field declaration (includes enum constants) */

FIELD,


/** Method declaration */

METHOD,


/** Formal parameter declaration */

PARAMETER,


/** Constructor declaration */

CONSTRUCTOR,


/** Local variable declaration */

LOCAL_VARIABLE,


/** Annotation type declaration */

ANNOTATION_TYPE,


/** Package declaration */

PACKAGE,


/** Type parameter declaration */

TYPE_PARAMETER,


/** Use of a type */

TYPE_USE

}



复制代码

@Inherited:允许子类继承父类中的注解,可以通过反射获取到父类的注解


@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Inherited {


}



复制代码

@Constraint:用于校验属性值是否合法


@Documented

@Target({ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

public @interface Constraint {

Class<? extends ConstraintValidator>[] validatedBy();

}


复制代码

@Retention:注解的声明周期,用于定义注解的存活阶段,可以存活在源码级别、编译级别(字节码级别)、运行时级别

SOURCE:源码级别,注解只存在源码中,一般用于和编译器交互,用于检测代码。如@Override, @SuppressWarings。

CLASS:字节码级别,注解存在于源码和字节码文件中,主要用于编译时生成额外的文件,如XML,Java文件等,但运行时无法获得。 如mybatis生成实体和映射文件,这个级别需要添加JVM加载时候的代理(javaagent),使用代理来动态修改字节码文件。

RUNTIME:运行时级别,注解存在于源码、字节码、java虚拟机中,主要用于运行时,可以使用反射获取相关的信息。


@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Retention {

/**

* Returns the retention policy.

* @return the retention policy

*/

RetentionPolicy value();

}


复制代码

3. Java注解的内容

在上面的注解源码中可以看到有的注解中没有任何内容,有的注解的有内容,看似像方法。

注解的内容的语法格式: 数据类型 属性名() default 默认值,数据类型用于描述属性的数据类型,默认值是说当没有给属性赋值时使用默认值,一般String使用空字符串”“作为默认值,数组一般使用空数组{ }作为默认值.

下面看一下SpringMVC中的RequestMapping的注解的声明


@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Mapping

public @interface RequestMapping {

String name() default "";


@AliasFor("path")

String[] value() default {};


@AliasFor("value")

String[] path() default {};


RequestMethod[] method() default {};

String[] params() default {};

String[] headers() default {};

String[] consumes() default {};

String[] produces() default {};

}



复制代码

使用SpringMVC中的RequestMapping注解


@RequestMapping(value = "/list",

method = RequestMethod.POST,

produces = {"application/json;charset=UTF-8;"})

public String list(){


}



复制代码

4. 注解的使用场景

可以通过注解的声明周期来分析注解的使用场景:

SOURCE源码级别:给编译器使用,如@Override、@Deprecated 等, 这部分开发者应该使用的场景不多

CLASS:字节码级别,这部分也很少见到

RUNTIME:运行时级别,这个是最多的,几乎开发者使用到的注解都是运行时级别,运行时注解常用的有以下几种情况 

注解中没有任何属性的,空的注解,这部分注解通常起到一个标注的作用,如@Test、@Before、@After,通过获取这些标记注解在逻辑上做一些特殊的处理

可以使用约束注解@Constraint来对属性值进行校验,如@Email, @NotNull等

可以通过在注解中使用属性来配置一些参数,然后可以使用反射获取这些参数,这些注解没有其他特殊的功能,只是简单的代替xml配置的方式来配置一些参数。使用注解来配置参数这在Spring boot中得到了热捧,如@Configuration

关于配置方式xml vs annotation, 一般使用xml配置一些和业务关系不太紧密的配置,使用注解配置一些和业务密切相关的参数。

三:Java注解和反射基本API


// 获取某个类型的注解

public A getAnnotation(Class annotationClass);

// 获取所有注解(包括父类中被Inherited修饰的注解)

public Annotation[] getAnnotations();

// 获取声明的注解(但是不包括父类中被Inherited修饰的注解)

public Annotation[] getDeclaredAnnotations();

// 判断某个对象上是否被某个注解进行标注

public boolean isAnnotationPresent(Class annotationClass)


// 获取某个类声明的所有字段

public Field[] getDeclaredFields() throws SecurityException;

// 获取某个方法

public Method getMethod(String name, Class... parameterTypes);



复制代码

四:自定义注解

使用自定义注解+拦截器或者是AOP等可以进行权限的控制。

下面通过定义一个注解用来限制当用户访问接口时必须要登录的示例

步骤一:定义注解 

RequiresLogin.java


@Documented

@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

public @interface RequiresLogin {


}



复制代码

步骤二:使用注解


@Controller

@RequestMapping("/user")

public class UserController {

@RequiresLogin

@RequestMapping(value = "/list", produces = {"application/json;charset=UTF-8;"})

public String getUserList(){


System.out.println("--------------");

return "[{'id': 1, 'username':'zhangsan'}]";

}

}



复制代码

步骤三:使用AOP进行拦截,解析注解


public class LoginAdvices {

public void before(JoinPoint joinPoint) throws Exception{


Object target = joinPoint.getTarget();

String methodName = joinPoint.getSignature().getName();


System.out.println(target + "-------" + methodName);

Method method = target.getClass().getMethod(methodName);

boolean annotationPresent = method.isAnnotationPresent(RequiresLogin.class);

if (annotationPresent) {

// 用户必须登录

boolean isLogin = false;

if (!isLogin) {

throw new Exception("访问该接口必须先登录");

} else {

System.out.println("已登录...");

}

}

}

}



复制代码

在applicationContext.xml中配置aop





复制代码

自定义异常

为什么要自定义异常 

Java虽然提供了丰富的异常处理类,但是在项目中还会经常使用自定义异常,其主要原因是Java提供的异常类在某些情况下还是不能满足各种业务的需求。 例如系统中有些错误是符合Java语法,但不符合业务逻辑。如当用户登录时账号不存在或者账号已锁定可以自定义一个账号异常AccountException。 

或者有些情况下Java的同一个异常可能会有多种原因引起,在排查问题时不容易定位错误,此时可以使用自定义一个更加明确的异常。

自定义异常的好处:自定义异常可以使异常更加明确,可以隐藏底层的异常,这样更安全,异常信息更加直观。

自定义异常的使用:自定义异常一般继承自Exception或者RuntimeException,根据业务需要可以带一些属性作为构造函数的参数,自定义异常需要程序员手动抛出异常,并处理异常。

下面是Apache Shiro中自定义异常的示例


public class ShiroException extends RuntimeException {

public ShiroException() {

}


public ShiroException(String message) {

super(message);

}


public ShiroException(Throwable cause) {

super(cause);

}


public ShiroException(String message, Throwable cause) {

super(message, cause);

}

}

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

擅长针对企业软件开发的产品设计及开发的细节与流程设计课程内容。座右铭:大道至简!

  • 370
    文章
  • 22914
    人气
  • 87%
    受欢迎度

已有23人表明态度,87%喜欢该老师!

进入TA的空间
求职秘籍 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
WEB前端必须会的基本知识题目
经验技巧 93% 的用户喜欢
Java语言中四种遍历List的方法总结(推荐)
经验技巧 91% 的用户喜欢
Java语言之SHA-256加密的两种实现方法详解
经验技巧 75% 的用户喜欢
java语言实现把两个有序数组合并到一个数组的实例
经验技巧 75% 的用户喜欢
通过Java语言代码来创建view的方法
经验技巧 80% 的用户喜欢
其他海同师资 更多>>
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
孔庆琦
孔庆琦 联系TA
对MVC模式和三层架构有深入的研究
周鸣君
周鸣君 联系TA
擅长Hadoop/Spark大数据技术
范佺菁
范佺菁 联系TA
擅长Java语言,只有合理的安排和管理时间你才能做得更多,行得更远!
金延鑫
金延鑫 联系TA
擅长与学生或家长及时有效沟通
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程