Java注解(Annotation)学习

Flchy 于 2016-05-15 发布

概念

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

注解的分类

  1. 源码注解

    注解只在源码中存在,编译成.class文件就不存在了。

  2. 编译时注解:

    注解在源码和.class文件中都存在。(例如:JDK的三个注解)

  3. 运行时注解

    在运行阶段还起作用,甚至会影响运行逻辑的注解

JDK自带注解

@Override //表示当前方法覆盖了父类的方法
@Deprecation //表示方法已经过时,方法上有横线,使用时会有警告。
@SuppviseWarnings //表示关闭一些警告信息(通知java编译器忽略特定的编译警告)

自定义注解

为了开发方便或者开发框架有时候需要自定义注解

语法

  1. 使用@interface关键字定义注解,注意关键字的位置
  2. 成员以无参数无异常的方式声明,注意区别一般类成员变量的声明
  3. 可以使用default为成员指定一个默认值,如上所示
  4. 成员类型是受限的,合法的类型包括原始类型以及String、Class、Annotation、Enumeration (JAVA的基本数据类型有8种:byte(字节)、short(短整型)、int(整数型)、long(长整型)、float(单精度浮点数类型)、double(双精度浮点数类型)、char(字符类型)、boolean(布尔类型)
  5. 注解类可以没有成员,没有成员的注解称为标识注解,例如JDK注解中的@Override、@Deprecation
  6. 如果注解只有一个成员,并且把成员取名为value(),则在使用时可以忽略成员名和赋值号“=” ,例如JDK注解的@SuppviseWarnings ;如果成员名不为value,则使用时需指明成员名和赋值号”=”
public @interface Annotation_1 {  
    //仅仅用作标识  
}

public @interface Annotation_2 {  
    String value() default "null";
    //使用时@Annotation_2("haha")
}

public @interface Annotation_3 {  
    String name();
    int age();
    //使用时@Annotation_3(name="haha",age=18)
}

元注解

何为元注解?就是注解的注解,就是给你自己定义的注解添加注解,你自己定义了一个注解,但你想要你的注解有什么样的功能,此时就需要用元注解对你的注解进行说明了。元注解有4个.

注解处理器

即通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑

@MyAnnotation(name="MyName")
public class UseAnn {
	@MyAnnotation(name="测试",age=21)
	public void excute(){
		System.out.println("excute()执行....");
	}
}
try {
    Class<?> c = Class.forName("Test");
    //类上面是否有注解
    if(c.isAnnotationPresent(MyAnnotation.class)){
        MyAnnotation myAnnotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
        System.out.println(myAnnotation.name()+" "+myAnnotation.age());
    }else{
        System.out.println("该类没有被注解...");
    }
    //方法上是否有注解
    Method[] ms = c.getDeclaredMethods();
    for(Method method:ms){
        if (method.isAnnotationPresent(MyAnnotation.class)) {
            MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
            System.out.println(myAnnotation.name()+" "+myAnnotation.age());
            try {
                try {
                    method.invoke(c.newInstance(), null);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
} catch (ClassNotFoundException e) {
    System.out.println("没有加载到类....");
}

Demo 注解反射生成SQL语句

使用java注解来对用户表的每个字段或字段的组合条件进行动态生成SQL查询语句

//Table.java
@Target({ElementType.TYPE})  
@Retention(RetentionPolicy.RUNTIME)  
public @interface Table {
    String value();  
}

//Column.java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)

public @interface Column {
	String value();
}

//User.java
@Table("user")  
public class User { 

    @Column("id") 
    private int id;  

    @Column("user_name")  
    private String userName;  
  
    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;  
    } 
}

//ReturnQuery.java
public static String query(Object object){
	StringBuilder sqlStrBuilder = new StringBuilder();
	Class clazz = object.getClass();
	if (!clazz.isAnnotationPresent(Table.class)) {
		return null;
	}

	Table t = (Table) clazz.getAnnotation(Table.class);
	String tableName = t.value();
    sqlStrBuilder.append("select * from ").append(tableName).append(" where 1=1");
	Field[] fields = clazz.getDeclaredFields();
	for (Field field : fields) {
		if (field.isAnnotationPresent(Column.class)) {
			Column column = field.getAnnotation(Column.class);
			Object value = invokeGet(field.getName(), object);
			sqlStrBuilder.append(" and "+column.value()+"=" +value );
		}
	}
	return sqlStrBuilder.toString();
	
}

public static Object invokeGet(String fieldName,Object object) {
	try {
		PropertyDescriptor pd = new PropertyDescriptor(fieldName,object.getClass());
		return pd.getReadMethod().invoke(object, null);
	} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
		return null;
	}
}

//Test.java
User u = new User();  
u.setUserName("haha");
u.setId(10);

System.out.println(ReturnQuery.query(u));

为了减小篇幅Demo删掉了好多代码,跑起来会有点问题,但是用法体现出来就行了