Java自定义注解
Java 自定义注解
前言:这两天看了一下 Java 自定义注解的内容,然后按照我自己的理解写了两份代码,还挺有趣的,本文包括三个部分:注解的基础、通过注解进行赋值(结合了工厂方法模式)、通过注解进行校验。
一、注解的基础
1. 注解的定义:Java 文件叫做 Annotation,用 @interface 表示。
2. 元注解:@interface 上面按需要注解上一些东西,包括 @Retention、@Target、@Document、@Inherited 四种。
3. 注解的保留策略:
@Retention(RetentionPolicy.SOURCE) // 注解仅存在于源码中,在 class 字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在 class 字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.RUNTIME) // 注解会在 class 字节码文件中存在,在运行时可以通过反射获取到
4. 注解的作用目标:
@Target(ElementType.TYPE) // 接口、类、枚举、注解
@Target(ElementType.FIELD) // 字段、枚举的常量
@Target(ElementType.METHOD) // 方法
@Target(ElementType.PARAMETER) // 方法参数
@Target(ElementType.CONSTRUCTOR) // 构造函数
@Target(ElementType.LOCAL_VARIABLE) // 局部变量
@Target(ElementType.ANNOTATION_TYPE) // 注解
@Target(ElementType.PACKAGE) // 包
5. 注解包含在 javadoc 中:
@Documented
6. 注解可以被继承:
@Inherited
7. 注解解析器:用来解析自定义注解。
二、通过注解进行赋值(结合了工厂方法模式)
1. 自定义注解
package annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Inherited
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Init
{
public String value() default "";
}
2. 在数据模型使用注解
package model;import annotation.Init;
public class User
{
private String name;
private String age;</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getName() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> name; } @Init(value </span>= "liang"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setName(String name) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getAge() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> age; } @Init(value </span>= "23"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setAge(String age) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.age =<span style="color: rgba(0, 0, 0, 1)"> age; }
}
3. 用“构造工厂”充当“注解解析器”
package factory;import java.lang.reflect.Method;
import annotation.Init;
import model.User;
public class UserFactory
{
public static User create()
{
User user = new User();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取User类中所有的方法(getDeclaredMethods也行)</span> Method[] methods = User.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.getMethods(); </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Method method : methods) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果此方法有注解,就把注解里面的数据赋值到user对象</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (method.isAnnotationPresent(Init.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)) { Init init </span>= method.getAnnotation(Init.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); method.invoke(user, init.value()); } } } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) { e.printStackTrace(); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> user; }
}
4. 运行的代码
package app;import java.lang.reflect.InvocationTargetException;
import factory.UserFactory;
import model.User;
public class Test
{
public static void main(String[] args) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
User user = UserFactory.create();System.out.println(user.getName()); System.out.println(user.getAge()); }
}
5. 运行结果
liang
23
三、通过注解进行校验
1. 自定义注解
package annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Inherited
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Validate
{
public int min() default 1;</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> max() <span style="color: rgba(0, 0, 255, 1)">default</span> 10<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> isNotNull() <span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
}
2. 在数据模型使用注解
package model;import annotation.Validate;
public class User
{
@Validate(min = 2, max = 5)
private String name;@Validate(isNotNull </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String age; </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getName() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> name; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setName(String name) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getAge() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> age; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setAge(String age) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.age =<span style="color: rgba(0, 0, 0, 1)"> age; }
}
3. 注解解析器
package check;import java.lang.reflect.Field;
import annotation.Validate;
import model.User;
public class UserCheck
{
public static boolean check(User user)
{
if (user == null)
{
System.out.println("!!校验对象为空!!");
return false;
}</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取User类的所有属性(如果使用getFields,就无法获取到private的属性)</span> Field[] fields = User.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.getDeclaredFields(); </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Field field : fields) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果属性有注解,就进行校验</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (field.isAnnotationPresent(Validate.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)) { Validate validate </span>= field.getAnnotation(Validate.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">if</span> (field.getName().equals("age"<span style="color: rgba(0, 0, 0, 1)">)) { </span><span style="color: rgba(0, 0, 255, 1)">if</span> (user.getAge() == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (validate.isNotNull()) { System.out.println(</span>"!!年龄可空校验不通过:不可为空!!"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"年龄可空校验通过:可以为空"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">; } } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"年龄可空校验通过"<span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">if</span> (user.getAge().length() <<span style="color: rgba(0, 0, 0, 1)"> validate.min()) { System.out.println(</span>"!!年龄最小长度校验不通过!!"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"年龄最小长度校验通过"<span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">if</span> (user.getAge().length() ><span style="color: rgba(0, 0, 0, 1)"> validate.max()) { System.out.println(</span>"!!年龄最大长度校验不通过!!"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"年龄最大长度校验通过"<span style="color: rgba(0, 0, 0, 1)">); } } </span><span style="color: rgba(0, 0, 255, 1)">if</span> (field.getName().equals("name"<span style="color: rgba(0, 0, 0, 1)">)) { </span><span style="color: rgba(0, 0, 255, 1)">if</span> (user.getName() == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (validate.isNotNull()) { System.out.println(</span>"!!名字可空校验不通过:不可为空!!"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"名字可空校验通过:可以为空"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">; } } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"名字可空校验通过"<span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">if</span> (user.getName().length() <<span style="color: rgba(0, 0, 0, 1)"> validate.min()) { System.out.println(</span>"!!名字最小长度校验不通过!!"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"名字最小长度校验通过"<span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">if</span> (user.getName().length() ><span style="color: rgba(0, 0, 0, 1)"> validate.max()) { System.out.println(</span>"!!名字最大长度校验不通过!!"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> { System.out.println(</span>"名字最大长度校验通过"<span style="color: rgba(0, 0, 0, 1)">); } } } } </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">; }
}
4. 运行的代码
package app;import check.UserCheck;
import model.User;
public class Test
{
public static void main(String[] args)
{
User user = new User();user.setName(</span>"liang"<span style="color: rgba(0, 0, 0, 1)">); user.setAge(</span>"1"<span style="color: rgba(0, 0, 0, 1)">); System.out.println(UserCheck.check(user)); }
}
5. 运行结果
名字可空校验通过 名字最小长度校验通过 名字最大长度校验通过 年龄可空校验通过 年龄最小长度校验通过 年龄最大长度校验通过 true