Java基础篇记录 -- 自定义注解Annotaion
为什么要用自定义注解?
- 可保存在 class 文件中,降低维护成本。
- 无需工具支持,无需解析
- 编译期即可验证正确性,查错变得容易。
- 提升开发效率。
Annotation 缺点:
1、若要对配置项进行修改,不得不修改 Java 文件,重新编译打包应用。
2、配置项编码在 Java 文件中,可扩展性差。
元注解:
注解的保留策略:
@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中: //javadoc,如@autore JDK定义好的
@Documented
6.注解可以被继承:
@Inherited
实现过程:
一、定义注解
@Documented //是否在doc
@Inherited //可否被继承
@Target({ElementType.FIELD,ElementType.METHOD}) //作用目标
@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取
public @interface Init {
public String value() default "";
}
二、在目标上使用
public class User {
@Validate(min =2,max =5)
private String name;
@Validate(isNotnull =false)
private String age;
public String getName() {
return name;
}
@Init("heyonghao") //使用
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
@Init("23")
public void setAge(String age) {
this.age = age;
}
}
三、编写解析器(与反射关系相当紧密)
public class UserFactory {
public static User create(){
User user = new User();
Method[] methods = User.class.getMethods();//反射,获取user类的所有方法
try{
for (Method method : methods) {
if(method.isAnnotationPresent(Init.class)){ //判断时候是有注解的类
Init init = method.getAnnotation(Init.class); //此方法返回该元素的注解在此元素的指定注释类型(如果存在),否则返回null
method.invoke(user, init.value()); //赋值
}
}
}catch(Exception e){
e.printStackTrace();
return null;
}
return user;
}
}
User user=UserFactory.create();
System.out.println(user.getName()); //heyonghao
System.out.println(user.getAge()); //23