【java开发系列】—— 自定义注解

【java开发系列】—— 自定义注解
(一)使用案例
1.标准元注解
    @Documented 标记生成javadoc
  @Inherited 标记继承关系
  @Retention 注解的生存期
  @Target 标注的目标
2.package com.my.async;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Person {
    String name();
    int age();
}
3.package com.my.async;
@Person(name = "xingoo", age = 25)
public class test3 {
    public static void print(Class c) {
        System.out.println(c.getName());
        Person person = (Person) c.getAnnotation(Person.class);
        if (person != null) {
            System.out.println("name:" + person.name() + " age:"
                    + person.age());
        } else {
            System.out.println("person unknown!");
        }
    }
    public static void main(String[] args) {
        test3.print(test3.class);
    }
}
(二)Annotation和interface的异同
    annotation的类型使用关键字@interface而不是interface。它继承了java.lang.annotition.Annotition接口,并非申明了一个interface。
    Annotation类型、方法定义是独特的、受限制的。Annotation类型的方法必须申明为无参数、无异常抛出的。这些方法定义了Annotation的成员:方法名称为了成员名,而方法返回值称为了成员的类型。
    方法返回值必须为primitive类型、Class类型、枚举类型、Annotation类型或者由前面类型之一作为元素的一位数组。
    方法的后面可以使用default和一个默认数值来申明成员的默认值,null不能作为成员的默认值,这与我们在非Annotation类型中定义方法有很大不同。
    Annotation类型和他的方法不能使用Annotation类型的参数,成员不能是generic。只有返回值类型是Class的方法可以在Annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。
    Annotation类型又与接口有着近似之处。它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。
元注解
    @Target 表示该注解用于什么地方
    @Retention 表示在什么级别保存该注解信息
    @Documented 将此注解包含在 javadoc 中
    @Inherited 允许子类继承父类中的注解
@Target 的 ElemenetType 参数包括:
    ElemenetType.CONSTRUCTOR 构造器声明
    ElemenetType.FIELD 域声明(包括 enum 实例)
    ElemenetType.LOCAL_VARIABLE 局部变量声明
    ElemenetType.METHOD 方法声明
    ElemenetType.PACKAGE 包声明
    ElemenetType.PARAMETER 参数声明
    ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
@Retention 可选的 RetentionPolicy 参数包括:
    RetentionPolicy.SOURCE 注解将被编译器丢弃
    RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
    RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
示例代码:
//Test.java
//该注解用于方法声明
@Target(ElementType.METHOD)
//VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息
@Retention(RetentionPolicy.RUNTIME)
//允许子类继承父类中的注解
@Inherited
//将此注解包含在javadoc中
@Documented
public @interface Test {
    public int id();
    public String desc() default "no descrition";
}
public class DemoTest {
    @Test(id = 1, desc = "美丽的姑娘")
    public void method1() {
    }
    @Test(id=2)
    public void method2() {
    }

    @Test(id=3,desc="哎呦,原来如此")
    public void method3() {
    }   

    public static void main(String[] args) {
        Method[] methods = DemoTest.class.getDeclaredMethods();
        for(Method m:methods){

            boolean b = m.isAnnotationPresent(Test.class);
            if(b){
                Test annotation = m.getAnnotation(Test.class);
                System.out.println(annotation.id()+":"+annotation.desc());
            }

        }

    }
}    

(三)自定义注解与ORM结合
1)package com.my.tab;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}
2)
package com.my.tab;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}
3)package com.my.tab;
@Table("user")  
public class Filter {   
    @Column("id")  
    private int id;  
      
    @Column("user_name")  
    private String username;  
      
    @Column("nickname")  
    private String nickname;  
      
    @Column("age")  
    private int age;  
      
    @Column("city")  
    private String city;  
      
    @Column("email")  
    private String email;  
      
    @Column("mobile")  
    private String mobile;  
 
    public int getId() {  
        return id;  
    }  
 
    public void setId(int id) {  
        this.id = id;  
    }  
 
    public String getUsername() {  
        return username;  
    }  
 
    public void setUsername(String username) {  
        this.username = username;  
    }  
 
    public String getNickname() {  
        return nickname;  
    }  
 
    public void setNickname(String nickname) {  
        this.nickname = nickname;  
    }  
 
    public int getAge() {  
        return age;  
    }  
 
    public void setAge(int age) {  
        this.age = age;  
    }  
 
    public String getCity() {  
        return city;  
    }  
 
    public void setCity(String city) {  
        this.city = city;  
    }  
 
    public String getEmail() {  
        return email;  
    }  
 
    public void setEmail(String email) {  
        this.email = email;  
    }  
 
    public String getMobile() {  
        return mobile;  
    }  
 
    public void setMobile(String mobile) {  
        this.mobile = mobile;  
    }  
}  

4)package com.my.tab;
@Table("department")  
public class Filter2 {  
      
    @Column("id")  
    private int id;  
      
    @Column("name")  
    private String name;  
      
    @Column("leader")  
    private String leader;  
      
    @Column("amount")  
    private int amount;  
 
    public int getId() {  
        return id;  
    }  
 
    public void setId(int id) {  
        this.id = id;  
    }  
 
    public String getName() {  
        return name;  
    }  
 
    public void setName(String name) {  
        this.name = name;  
    }  
 
    public String getLeader() {  
        return leader;  
    }  
 
    public void setLeader(String leader) {  
        this.leader = leader;  
    }  
 
    public int getAmount() {  
        return amount;  
    }  
 
    public void setAmount(int amount) {  
        this.amount = amount;  
    }  
}  
5)package com.my.tab;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {  
    public static void main(String[] args) {  
        Filter f1 = new Filter();  
        f1.setId(10); //查询id为10的用户  
          
        Filter f2 = new Filter();  
        f2.setUsername("lucy"); //查询用户名为lucy的用户  
        f2.setAge(18);  
          
        Filter f3 = new Filter();  
        f3.setEmail("liu@sina.com, zh@163.com, 77777@qq.com"); //查询邮箱为其中任意一个的用户  
          
        String sql1 = query(f1);  
        String sql2 = query(f2);  
        String sql3 = query(f3);  
          
        System.out.println(sql1);  
        System.out.println(sql2);  
        System.out.println(sql3);  
          
          
        Filter2 filter2 = new Filter2();  
        filter2.setAmount(10);  
        filter2.setName("技术部");  
        System.out.println(query(filter2));  
          
    }  
      
    private static String query(Object f) {  
        StringBuilder sb = new StringBuilder();  
        //1.获取到class  
        Class c = f.getClass();  
          
        //2.获取到table的名字  
        boolean exists = c.isAnnotationPresent(Table.class);  
        if(!exists) {  
            return null;  
        }  
        Table t = (Table)c.getAnnotation(Table.class);  
        String tableName = t.value();  
          
        sb.append("select * from ").append(tableName).append(" where 1 = 1");  
        //3.遍历所有字段  
        Field[] fArray = c.getDeclaredFields();  
        for(Field field : fArray) {  
            //4.处理每个字段对应的sql  
            //4.1 拿到字段名  
            boolean fExists = field.isAnnotationPresent(Column.class);  
            if(!fExists) {  
                continue;  
            }  
            Column column = field.getAnnotation(Column.class);  
            String columnName = column.value();  
            //4.2 拿到字段的值  
            String fieldName = field.getName();  
            String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);  
            Object fieldValue = null;  
            try {  
                Method getMethod = c.getMethod(getMethodName);  
                  
                fieldValue = getMethod.invoke(f);  
                  
            } catch (NoSuchMethodException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            } catch (SecurityException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            } catch (IllegalAccessException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            } catch (IllegalArgumentException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            } catch (InvocationTargetException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
              
            //4.3 拼装sql  
            if(fieldValue == null || ((fieldValue instanceof Integer) && (Integer)fieldValue == 0)) {  
                continue;  
            }  
              
            sb.append(" and ").append(columnName);  
            if(fieldValue instanceof String) {  
                if(((String)fieldValue).contains(",")) {  
                    String[] values = ((String)fieldValue).split(",");  
                    sb.append(" in(");  
                    for(String v : values) {  
                        sb.append("'").append(v.trim()).append("'").append(",");  
                    }  
                    sb.deleteCharAt(sb.length() - 1);  
                    sb.append(")");  
                } else {  
                    sb.append("=").append("'").append(fieldValue).append("'");                    
                }  
                  
            } else if(fieldValue instanceof Integer) {  
                sb.append("=").append(fieldValue);  
            }  
              
        }  
          
        return sb.toString();  
    }  


(四)
1)package com.my.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.METHOD, ElementType.TYPE })
// JVM会读取注解,所以利用反射可以获得注解
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    // 定义成员变量
    // 成员变量可以通过default指定默认值
    // 如果成员变量不指定默认值的情况下
    // 我们在引用接口时则必须给没有默认值的成员变量赋值
    String name();

    int age() default 18;

}

2)package com.my.annotation;
@TestAnnotation(name="I'm class annotation")
public class Test {
    @TestAnnotation(name="I'm method annotation")
    public static void showAnnotation(){

    }

}

3)package com.my.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class testA {
    public static void main(String[] args) {
        //解析注解
        //获得我们需要解析注解的类
        Class<Test> clz = Test.class;

        //解析Class
        //由于我们的注解是可以给类使用的,所以首先判断类上面有没有我们的注解
        //判断类上面是否有注解
        boolean clzHasAnnotation = clz.isAnnotationPresent(TestAnnotation.class);
        if(clzHasAnnotation){
            //类存在我们定义的注解
            //获得注解
            TestAnnotation clzAnnotation = clz.getAnnotation(TestAnnotation.class);
            //输出注解在类上的属性
            System.out.println("name="+clzAnnotation.name()+"\tage="+clzAnnotation.age());
        }

        //解析Method
        //两种解析方法上的注解方式
        //获得类中所有方法
        Method[] methods = clz.getMethods();
        //第一种解析方法
        for(Method m : methods){
            //获得方法中是否含有我们的注解
            boolean methodHasAnnotation = m.isAnnotationPresent(TestAnnotation.class);
            if(methodHasAnnotation){
                //注解存在
                //获得注解
                TestAnnotation methodAnnotation = m.getAnnotation(TestAnnotation.class);

                System.out.println("name="+methodAnnotation.name()+"\tage="+methodAnnotation.age());
            }
        }
        //第二种解析方式
        for(Method m : methods){
            //获得方法上所有注解
            Annotation[] annotations = m.getAnnotations();
            //循环注解
            for(Annotation a : annotations){
                //如果是我们自定义的注解
                if(a instanceof TestAnnotation){
                    //输出属性,需要强制装换类型
                    System.out.println("name="+((TestAnnotation)a).name()+"\tage="+((TestAnnotation)a).age());
                }
            }
        }

    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值