自己动手写注解实现业务bean的字段验证

我们用过 JDK给我们提供的  @Override  @Deprecated @SuppressWarning 注解  ,这些注解是JDK给我们提供的 ,我们只是在用别人写好的东西 ,那么我们是否可以自己写注解呢?当然是可以的  。

我们写的注解包括三个环节 

1、 注解的声明 ,也就是注解类的定义     形式如下        @interface 来进行注解的声明

package annotate;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)  //这个标识注解应该标在那里   ElementType的几个枚举值就代表了  注解应该写在的位置 
@Retention(RetentionPolicy.RUNTIME)  //指定了注解保留的周期 
public @interface CheckString {
  
}

@Retention(RetentionPolicy.RUNTIME)   

指定了注解保留的周期 注解的生命周期有是三个   RetentionPolicy 枚举的三个值代表了三个声明周期  默认是CLASS

枚举常量摘要
CLASS
          编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。
RUNTIME
          编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
SOURCE
          编译器要丢弃的注释。

 

@Target(ElementType.TYPE) 

这个标识注解应该标在那里   ElementType的几个枚举值就代表了  注解应该写在的位置

 

CONSTRUCTOR
          构造方法声明
FIELD
          字段声明(包括枚举常量)
LOCAL_VARIABLE
          局部变量声明
METHOD
          方法声明
PACKAGE
          包声明
PARAMETER
          参数声明
TYPE
          类、接口(包括注释类型)或枚举声明
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

Annotation类型里面的参数该怎么设定:
  第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;   
  第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;

package annotate;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)  //这个标识注解应该标在那里   ElementType的几个枚举值就代表了  注解应该写在的位置 
@Retention(RetentionPolicy.RUNTIME)  //指定了注解保留的周期 
public @interface CheckString {
	/**
	 * 检验的正则表达式
	 */
	String regex() default ".*";

	/**
	 * 字段是否需要填写
	 */
	Exists exists() default Exists.Skipped;
	
	/**
	 * 字段最小长度
	 * @return
	 */
	int minlen() default 0;
	
	
	/**
	 * 字段最大长度
	 * @return
	 */
	int maxlen() default Short.MAX_VALUE;
}
枚举类:
package annotate;

public enum Exists {
	/**
	 * 跳过检验
	 */
	Skipped,
	
	/**
	 * 禁止填写
	 */	
	Prohibit,
	
	/**
	 * 非空字段
	 */	
	Required,
	
	/**
	 * 可选字段
	 */
	Optional
}

注解使用类:

package model;

import annotate.CheckString;
import annotate.Exists;

public class Persion {
  @CheckString(exists=Exists.Required)
  public String test;
  @CheckString(exists=Exists.Required)
  private String name;
  @CheckString(exists=Exists.Required)
  private String password;
  private String sex;
  private int age;
  
  public String getPassword() {
	return password;
}
public void setPassword(String password) {
	this.password = password;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public String getSex() {
	return sex;
}
public void setSex(String sex) {
	this.sex = sex;
}
public int getAge() {
	return age;
}
public void setAge(int age) {
	this.age = age;
}
@Override
public String toString() {
	return "Persion [name=" + name + ", password=" + password + ", sex=" + sex + ", age=" + age + ", test=" + test + "]";
}
public Persion(String name, String password) {
	super();
	this.name = name;
	this.password = password;
}
  


}

利用反射来操作注解  

Class类有一个 方法

 


A
   getAnnotation(Class annotationClass)

 

这个方法接受一个注解的字节码参数  ,然后返回这个类所标识的注解对象 ,因为我们标识了一个注解就相当于产生了一个注解对象  。

 

boolean isAnnotationPresent(Class annotationClass)

 

这个方法判断一个类是否被注解所标识

下面是代码示例

public class CheckParamUtil {
   public static void checkParam(Object o) throws Exception{
		 out:{
		   final Class objClass=o.getClass();
		   Field[] farray=objClass.getDeclaredFields();//获取所有字段  包括private 不包括父类字段
		   Class chkString=CheckString.class;//CheckString的class
		   for(int i=0;i

验证:

public class TestCheckParam {
    public static void main(String[] args) {
		Persion p=new Persion("zhangsan","111111");
		try {
			CheckParamUtil.checkParam(p);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

控制太打印:Persion.test必须填写

你可能感兴趣的:(架构)