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() &lt;<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() &gt;<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() &lt;<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() &gt;<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