Java自定义注解Annotation的使用

从 jdk5开始,Java增加了对元数据的支持,也就是Annotation,Annotation其实就是对代码的一种特殊标记,这些标记可以在编译,类加载和运行时被读取,并执行相应的处理。当然刚刚说了,Annotation只是一种标记,所以要是在代码里面不用这些标记也是能完成相应的工作的,只是有时候用注解能简化很多代码,看起来非常的简洁。

常见的注解(Annotation)

@Override——限定重写父类方法

@Deprecated——标示已过时

@SuppressWarning——抑制编译器警告

JAVA的元注解

除了上面的注解,还有元注解。元注解是指注解的注解,包括@Retention @Target @Document @Inherited四种。

[email protected] 这个是决定你Annotation存活的时间的,它包含一个RetationPolicy的value成员变量,用于指定它所修饰的Annotation保留时间,一般有:

1. Retationpolicy.CLASS:编译器将把注解记录在Class文件中,

不过当java程序执行的时候,JVM将抛弃它。不过当java程序执行的时候,JVM将抛弃它。

2. Retationpolicy.SOURCE : 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得。

4. Retationpolicy.RUNTIME : 在Retationpolicy.CLASS的基础上,JVM执行的时候也不会抛弃它,所以我们一般在程序中可以通过反射来获得这个注解,然后进行处理。

首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以MT4下载教程前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。

[email protected] 这个注解一般用来指定被修饰的注解修饰哪些元素,如下:

ElementType.ANNOTATION_TYPE : //注解

ElementType.CONSTRUCTOR: //构造函数

ElementType.FIELD: //字段、枚举的常量

ElementType.LOCAL_VARIABLE: //局部变量

ElementType.METHOD: //方法

ElementType.PACKAGE: //包

ElementType.PARAMETER://方法参数

ElementType.TYPE: //接口、类、枚举、注解

@Document 这个注解修饰的Annotation类可以被javadoc工具提取成文档

@Inherited 被他修饰的注解具有继承性,说明子类可以继承父类中的该注解

例子

自定义注解MyClassAnnotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface MyClassAnnotation {

String value();

}

自定义注解MyFieldAnnotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface MyFieldAnnotation {

public String name() default "fieldName";

}

自定义注解MyMethodAnnotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface MyMethodAnnotation {

String name();

int age();

}

在实例中使用TestRuntimeAnnotation 来测试注解情况:

@MyClassAnnotation(value = "test Class")

public class TestRuntimeAnnotation {

@MyFieldAnnotation

public String fieldInfo = "FiledInfo";

@MyMethodAnnotation(age = 0, name = "zhangsan")

public static String getMethodInfo() {

return TestRuntimeAnnotation.class.getSimpleName();

}

public static void main(String[]args) {

StringBuffer sb = new StringBuffer();

Class<?> cls = TestRuntimeAnnotation.class;

sb.append("Class注解:").append("\n");

MyClassAnnotation myClassAnnotation = cls.getAnnotation(MyClassAnnotation.class);

if (myClassAnnotation != null) {

sb.append(Modifier.toString(cls.getModifiers())).append(" ")

.append(cls.getSimpleName()).append("\n");

sb.append("注解值: ").append(myClassAnnotation.value()).append("\n\n");

}

sb.append("Field注解:").append("\n");

Field[] fields = cls.getDeclaredFields();

for (Field field : fields) {

MyFieldAnnotation fieldInfo = field.getAnnotation(MyFieldAnnotation.class);

if (fieldInfo != null) {

sb.append(Modifier.toString(field.getModifiers())).append(" ")

.append(field.getType().getSimpleName()).append(" ")

.append(field.getName()).append("\n");

sb.append("注解值: ").append(fieldInfo.name()).append("\n\n");

}

}

sb.append("Method注解:").append("\n");

Method[] methods = cls.getDeclaredMethods();

for (Method method : methods) {

MyMethodAnnotation methodInfo = method.getAnnotation(MyMethodAnnotation.class);

if (methodInfo != null) {

sb.append(Modifier.toString(method.getModifiers())).append(" ")

.append(method.getReturnType().getSimpleName()).append(" ")

.append(method.getName()).append("\n");

sb.append("注解值: ").append("\n");

sb.append("name: ").append(methodInfo.name()).append("\n");

sb.append("age: ").append(methodInfo.age()).append("\n");

}

}

System.out.print(sb.toString());

}

}

测试结果如下:

Class注解:

public TestRuntimeAnnotation

注解值: test Class

Field注解:

public String fieldInfo

注解值: fieldName

Method注解:

public static String getMethodInfo

注解值:

name: zhangsan

age: 0

定义注解

该注解可以验证成员属性是否为空,长度,提供了几种常见的正则匹配,也可以使用自定义的正则去判断属性是否合法,同时可以为该成员提供描述信息。

定义注解

该注解可以验证成员属性是否为空,长度,提供了几种常见的正则匹配,也可以使用自定义的正则去判断属性是否合法,同时可以为该成员提供描述信息。

package org.xdemo.validation.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import org.xdemo.validation.RegexType;

/**

* 数据验证

* @author Goofy

*/

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD,ElementType.PARAMETER})

public @interface DV {

//是否可以为空

boolean nullable() default false;

//最大长度

int maxLength() default 0;

//最小长度

int minLength() default 0;

//提供几种常用的正则验证

RegexType regexType() default RegexType.NONE;

//自定义正则验证

String regexExpression() default "";

//参数或者字段描述,这样能够显示友好的异常信息

String description() default "";

}

注解的解析

package org.xdemo.validation.annotation.support;

import java.lang.reflect.Field;

import org.xdemo.validation.RegexType;

import org.xdemo.validation.annotation.DV;

import org.xdemo.validation.utils.RegexUtils;

import org.xdemo.validation.utils.StringUtils;

/**

* 注解解析

* @author Goofy

*/

public class ValidateService {

private static DV dv;

public ValidateService() {

super();

}

//解析的入口

public static void valid(Object object) throws Exception{

//获取object的类型

Class<? extends Object> clazz=object.getClass();

//获取该类型声明的成员

Field[] fields=clazz.getDeclaredFields();

//遍历属性

for(Field field:fields){

//对于private私有化的成员变量,通过setAccessible来修改器访问权限

field.setAccessible(true);

validate(field,object);

//重新设置会私有权限

field.setAccessible(false);

}

}

public static void validate(Field field,Object object) throws Exception{

String description;

Object value;

//获取对象的成员的注解信息

dv=field.getAnnotation(DV.class);

value=field.get(object);

if(dv==null)return;

description=dv.description().equals("")?field.getName():dv.description();

/*************注解解析工作开始******************/

if(!dv.nullable()){

if(value==null||StringUtils.isBlank(value.toString())){

throw new Exception(description+"不能为空");

}

}

if(value.toString().length()>dv.maxLength()&&dv.maxLength()!=0){

throw new Exception(description+"长度不能超过"+dv.maxLength());

}

if(value.toString().length()<dv.minLength()&&dv.minLength()!=0){

throw new Exception(description+"长度不能小于"+dv.minLength());

}

if(dv.regexType()!=RegexType.NONE){

switch (dv.regexType()) {

case NONE:

break;

case SPECIALCHAR:

if(RegexUtils.hasSpecialChar(value.toString())){

throw new Exception(description+"不能含有特殊字符");

}

break;

case CHINESE:

if(RegexUtils.isChinese2(value.toString())){

throw new Exception(description+"不能含有中文字符");

}

break;

case EMAIL:

if(!RegexUtils.isEmail(value.toString())){

throw new Exception(description+"地址格式不正确");

}

break;

case IP:

if(!RegexUtils.isIp(value.toString())){

throw new Exception(description+"地址格式不正确");

}

break;

case NUMBER:

if(!RegexUtils.isNumber(value.toString())){

throw new Exception(description+"不是数字");

}

break;

case PHONENUMBER:

if(!RegexUtils.isPhoneNumber(value.toString())){

throw new Exception(description+"不是数字");

}

break;

default:

break;

}

}

if(!dv.regexExpression().equals("")){

if(value.toString().matches(dv.regexExpression())){

throw new Exception(description+"格式不正确");

}

}

/*************注解解析工作结束******************/

}

}

用到的几个类

package org.xdemo.validation;

/**

* 常用的数据类型枚举

* @author Goofy

*

*/

public enum RegexType {

NONE,

SPECIALCHAR,

CHINESE,

EMAIL,

IP,

NUMBER,

PHONENUMBER;

}

其中正则验证类和字符串工具类请参考以下链接:

SuperUtil之RegexUtils

SuperUtil之StringUtils

使用方法

package org.xdemo.validation.test;

import org.xdemo.validation.RegexType;

import org.xdemo.validation.annotation.DV;

public class User {

@DV(description="用户名",minLength=6,maxLength=32,nullable=false)

private String userName;

private String password;

@DV(description="邮件地址",nullable=false,regexType=RegexType.EMAIL)

private String email;

public User(){}

public User(String userName, String password, String email) {

super();

this.userName = userName;

this.password = password;

this.email = email;

}

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

}

测试代码

import org.xdemo.validation.annotation.support.ValidateService;

/**

* @author Goofy

*/

public class Test {

public static void main(String[] args){

User user=new User("张三", "xdemo.org", "[email protected]");

try {

ValidateService.valid(user);

} catch (Exception e) {

e.printStackTrace();

}

user=new User("zhangsan","xdemo.org","[email protected]");

try {

ValidateService.valid(user);

} catch (Exception e) {

e.printStackTrace();

}

user=new User("zhangsan","xdemo.org","");

try {

ValidateService.valid(user);

} catch (Exception e) {

e.printStackTrace();

}

}

}

原文地址:https://www.cnblogs.com/benming/p/11640856.html

时间: 2024-10-22 03:23:46

Java自定义注解Annotation的使用的相关文章

Java自定义注解Annotation详解

注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事.标记可以加在包,类,字段,方法,方法的参数以及局部变量上. 自定义注解及其应用 1).定义一个最简单的注解 public @interface MyAnnotation { //...... } 2).把注解加在某个类上: @MyAnnotation public class Annot

java自定义注解类

一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Tar

Java Android 注解(Annotation) 及几个常用开源项目注解原理简析

不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义.解析,并对几个 Android 开源库 Annotation 原理进行简析.PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 完整版原文见:Java Android 注解(Ann

深入 Java自定义注解

我们在使用Spring框架的时候,会经常使用类似:@Autowired 这样的注解.我们也可以自己定义一些注解.Java的注解主要在包:java.lang.annotation中实现. 1. 元注解 什么是元注解?你可以这样理解,元注解是自定义注解的注解.元注解主要包含4个.他们主要在java.lang.annotation中可以找到.我们自己要创建注解的时候必须要用到这些元注解.所以必须彻底理解这四个元注解的含义. 1. @Documented 2. @Inherited 3. @Retent

spring中自定义注解(annotation)与AOP中获取注解

一.自定义注解(annotation) 自定义注解的作用:在反射中获取注解,以取得注解修饰的类.方法或属性的相关解释. package me.lichunlong.spring.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.R

Java自定义注解反射校验数据

package com.annotations.ecargo; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUN

gradle编译自定义注解(annotation)

最近把一个用eclipse构建的项目,加上了Gradle脚本,用它来编译.虽然最后编译是显示BUILD SUCCESSFUL,但是在编译过程中,却打印出一大堆栈信息,似乎是在编译我自定义的注解时出现的异常. 打印的栈信息前面部分如下: :assemble :lint Failed converting ECJ parse tree to Lombok for file E:\code\git\androidkit\andro idkit\src\com\lurencun\cfuture09\an

Java:注解Annotation(元数据)

本文内容: 注解Annotation的介绍 基本注解的用法 首发日期:2018-07-28 注解Annotation的介绍 Annotation是代码中的特殊标记,能够在编译.类加载.运行时被识别(需要设置),并根据不同的Annotation来执行不同的处理. Annotation可以修饰包.类.构造器.函数.成员变量.局部变量的声明.参数等程序元素.Annotation帮助这些元素来设置元数据,程序从元数据中获取信息来处理这些元素. 元数据可以描述代码间关系或者代码与其它资源的关系,比如说在w

Java自定义注解

自定义注解类编写的一些规则: 1. Annotation型定义为@interface, 所有的Annotation会自动继承Java.lang.Annotation这一接口,并且不能再去继承别的类或是接口. 2. 参数成员只能用public或默认(default)这两个访问权修饰 3. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String.Enum.Class.annotations等数据类型,以及这一些类