如果此刻不方便阅读,可收藏或关注微信公众号《程序新视界》回复“注解”获得PDF版本。
注解(Annontation),Java5引入的新特性,位于java.lang.annotation包中。提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。是一种说明、配置、描述性的信息,与具体业务无关,也不会影响正常的业务逻辑。但我们可以用反射机制来进行校验、赋值等操作。
常见的注解:@Override,@author,@param,@Deprecated,@SuppressWarnings。
元注解是专门用来注解其他注解的注解,听起来有些绕口,实际上就是专门为自定义注解提供的注解。java.lang.annotation提供了四种元注解:
通过@Retention定义注解的生命周期,格式如下:
@Retention(RetentionPolicy.SOURCE)
其中RetentionPolicy的不同策略对应的生命周期如下:
通过@Target定义注解作用的目标,比如作用于类、属性、或方法等,默认可用于任何地方。格式如下:
@Target(ElementType.TYPE)
对应ElementType参数值适用范围如下:
@Documented,表示是否将此注解的相关信息添加到javadoc文档中。
@Inherited,定义该注解和子类的关系,使用此注解声明出来的自定义注解,在使用在类上面时,子类会自动继承此注解,否则,子类不会继承此注解。注意,使用Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效。
下面通过一个实例来演示注解的使用:通过注解进行赋值和通过注解进行校验。
这里定义两个注解,一个用来赋值,一个用来校验。
/**
* 性别赋值
* @author zzs
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
@Inherited
public @interface InitSex {
/**
* sex enum
* @author zzs
*/
enum SEX_TYPE {MAN, WOMAN}
SEX_TYPE sex() default SEX_TYPE.MAN;
}
/**
* 年龄校验
* @author zzs
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
@Inherited
public @interface ValidateAge {
/**
* 最小值
*/
int min() default 18;
/**
* 最大值
*/
int max() default 99;
/**
* 默认值
*/
int value() default 20;
}
这里用User类来表示具体待处理的数据对象。
/**
* user
*
* @author zzs
*/
public class User {
private String username;
@ValidateAge(min = 20, max = 35, value = 22)
private int age;
@InitSex(sex = InitSex.SEX_TYPE.MAN)
private String sex;
// 省略getter/setter方法
}
具体测试调用的过程,参考代码中的注解,其中initUser方法来演示通过反射给属性赋值,checkUser方法通过反射拿到当前属性的值进行对比校验。
import java.lang.reflect.Field;
/**
* @author zzs
*/
public class TestInitParam {
public static void main(String[] args) throws IllegalAccessException {
User user = new User();
initUser(user);
// 年龄为0,校验为通过情况
boolean checkResult = checkUser(user);
printResult(checkResult);
// 重新设置年龄,校验通过情况
user.setAge(22);
checkResult = checkUser(user);
printResult(checkResult);
}
static void initUser(User user) throws IllegalAccessException {
// 获取User类中所有的属性(getFields无法获得private属性)
Field[] fields = User.class.getDeclaredFields();
// 遍历所有属性
for (Field field : fields) {
// 如果属性上有此注解,则进行赋值操作
if (field.isAnnotationPresent(InitSex.class)) {
InitSex init = field.getAnnotation(InitSex.class);
field.setAccessible(true);
// 设置属性的性别值
field.set(user, init.sex().toString());
System.out.println("完成属性值的修改,修改值为:" + init.sex().toString());
}
}
}
static boolean checkUser(User user) throws IllegalAccessException {
// 获取User类中所有的属性(getFields无法获得private属性)
Field[] fields = User.class.getDeclaredFields();
boolean result = true;
// 遍历所有属性
for (Field field : fields) {
// 如果属性上有此注解,则进行赋值操作
if (field.isAnnotationPresent(ValidateAge.class)) {
ValidateAge validateAge = field.getAnnotation(ValidateAge.class);
field.setAccessible(true);
int age = (int) field.get(user);
if (age < validateAge.min() || age > validateAge.max()) {
result = false;
System.out.println("年龄值不符合条件");
}
}
}
return result;
}
static void printResult(boolean checkResult) {
if (checkResult) {
System.out.println("校验通过");
} else {
System.out.println("校验未通过");
}
}
}
打印日志:
完成属性值的修改,修改值为:MAN
年龄值不符合条件
校验未通过
校验通过
在具体项目实战中更多的使用拦截器或切面来进行处理,结合具体的场景进行相应的发挥,这里不再赘述。
更多资料可关注微信公众号,回复对应关键字,本篇回复“注解”获得PDF版本。