- Annotation(注释) 概述
Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理. 通过使用 Annotation, 程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息。Annotation 可以像修饰符一样被使用, 可用于修饰包,类, 构造器, 方法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在 Annotation 的 “name=value” 对中。Annotation 能被用来为程序元素(类, 方法, 成员变量等) 设置元数据
- 为什么使用注解
2,以用来生成描述符文件,甚至或是新的类定义,并且有助于减轻
3,更加干净易读的代码以及编译器类型检查编写样板代码的负担
- JDK内置注解
@Override: 限定重写父类方法, 该注释只能用于方法,表示一个方法声明打算重写超类中的另一个方法声明。
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择@SuppressWarnings: 抑制编译器警告。
package linkin; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * * @version 1L * @author LinkinPark * @since 2014-11-27 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^3个常用的注解 */ @SuppressWarnings("all") public class Linkin { @Override public String toString() { return ""; } public void test() { Date date = new Date(); int year = date.getYear(); int year1 = Calendar.getInstance().get(Calendar.YEAR); } @SuppressWarnings("unchecked") public void test1() { List<String> linkin = new ArrayList(); } }
- 自定义 Annotation
修饰符 @interface 名{
类型 元素名() [default value]
}
package linkin; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * * @version 1L * @author LinkinPark * @since 2014-11-27 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^如果Annotation的成员变量名为value的时候,程序中可以直接在Annotation后面的括号里面指定该成员变量的值,无须使用name=value的形式 */ //如果要指定多个作用域,可以传入一个数组@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR }) @Target(ElementType.METHOD) //一般都是RUNTIME,来运行时通过反射也可以获得这个注解。@Retention(value=RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME) public @interface LinkinAnnotation { String value() default ""; String name() default ""; String[] names(); }
- JDK 的元 Annotation
1,@Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留多长时间, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用 @Rentention 时必须为该 value 成员变量指定值:
RetentionPolicy.CLASS: 编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注释. 这是默认值
RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注释. 程序可以通过反射获取该注释
RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注释
2,@Target: 用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素. @Target 也包含一个名为 value 的成员变量
3,@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档
4,@Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注释。
上面的元注解经常用到就下面2个:@Target 该注解可以用于哪些地方。@Retention 表示需要在什么级别保存该注解信息
- 提取 Annotation 信息
当一个 Annotation 类型被定义为运行时 Annotation 后, 该注释才是运行时可见, 当 class 文件被载入时保存在 class 文件中的 Annotation 才会被虚拟机读取
程序可以调用 AnnotationElement 对象的如下方法来访问 Annotation 信息。
- 什么是注解处理器
package com.tanlan.crm.base.ap; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; /** * * @version 1L * @author LinkinPark * @since 2014-11-27 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^模拟juit测试框架,即打了test注解的方法能被执行 */ public class AnnoatationProcess { public void process(TestDemo testDemo) throws Exception { Class<TestDemo> c = TestDemo.class; Method[] methods = c.getDeclaredMethods(); for (Method method : methods) { // 判断方法是否使用了Test注解 if (method.isAnnotationPresent(Test.class)) { method.invoke(testDemo); } } } public static void main(String[] args) throws Exception { TestDemo testDemo=new TestDemo(); AnnoatationProcess process=new AnnoatationProcess(); process.process(testDemo); } } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface Test { } class TestDemo { @Test public void test1() { System.out.println("test1"); } @Test public void test2() { System.out.println("test2"); } }
下面代码模拟了hibernate的实体注解映射:
package com.tanlan.crm.base.ap; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.lang.reflect.Method; public class DAO { public void add1(User user) throws Exception { String sql = "insert into "; String values = ""; Class<User> c = User.class; if (c.isAnnotationPresent(Table.class)) { Table t = c.getAnnotation(Table.class); String tableName = t.value(); if (tableName.equals("")) { tableName = c.getSimpleName(); } sql += tableName + "("; Field[] fields = c.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { Column col = field.getAnnotation(Column.class); String colName = col.value(); if (colName.equals("")) { colName = field.getName(); } sql += colName + ","; Method method = c.getDeclaredMethod("get" + toUpper(colName)); Object v = method.invoke(user); values += "'" + v + "',"; } } } sql = sql.substring(0, sql.length() - 1); sql += ") values(" + values.substring(0, values.length() - 1) + ")"; System.out.println(sql); } public <E> void add(E e) throws Exception { String sql = "insert into "; String values = ""; Class<?> c = e.getClass(); if (c.isAnnotationPresent(Table.class)) { Table t = c.getAnnotation(Table.class); String tableName = t.value(); if (tableName.equals("")) { tableName = c.getSimpleName(); } sql += tableName + "("; Field[] fields = c.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { Column col = field.getAnnotation(Column.class); String colName = col.value(); if (colName.equals("")) { colName = field.getName(); } sql += colName + ","; Method method = c.getDeclaredMethod("get" + toUpper(colName)); Object v = method.invoke(e); values += "'" + v + "',"; } } } sql = sql.substring(0, sql.length() - 1); sql += ") values(" + values.substring(0, values.length() - 1) + ")"; System.out.println(sql); } private static String toUpper(String s) { String first = s.substring(0, 1); return first.toUpperCase() + s.substring(1); } public static void main(String[] args) throws Exception { User user=new User(); user.setName("Tom"); user.setPassword("123456"); DAO dao=new DAO(); dao.add(user); Product product=new Product(); product.setName("电视"); dao.add(product); } } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Table { String value() default ""; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Column { String value() default ""; } @Table class User { @Column("name") private String name; @Column private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } @Table("crm_product") class Product { @Column private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }