注解是什么
我们在平时的工作中,可能会看到形如一下的代码:
@Entity(tableName = "user")
public class User{
@Id
@Column(name="id")
private long id;
@Column(name="uid")
private String uid;
...
}
这种标记在类上,方法上,@开头的就叫做注解.
注解的用处
上图是我们公司ORM框架的一个entity类,总所周知,ORM框架与数据库打交道,最后也要转为SQL语句.比如保存一条记录,数据库只接受INSERT INTO USER('id','uid') VALUES('1', 'huangzp')这样的保存方式,如果当我们操作 orm.save(user),这样的代码的时候,实际上也是将它转成SQL,那么对象要怎么转成SQL呢?可以看到,要转成SQL,至少要知道表名,字段,那么我们在类中标明类名和表名及成员变量和字段的对应关系不就OK了吗?当我们要保存保存数据的时候,通过反射取得这些注解,然后拼成SQL.完美! 所以注解相当于一个标记,我们最后还是得通过反射等手段获取这些注解,然后写成我们需要的功能.
定义一个注解
我们使用一个类的时候,我们要先去定义一个类,比如
public class Cat{}
同样的,我们要使用一个注解,同样也要去定义
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
//注解元素
String tableName() default "";
//快捷方式,我们设置了value的元素的时候,设置value的值的时候,只需要@Entity("haha")而不需要@Entity(value="haha")
String value() default "";
}
- @interface 是声明一个注解,就像我们class,enum一样.
- @Target 是注解修饰范围的范围,我们可以看一下ElementType这个枚举类
public enum ElementType {
/**注解在类名,接口名,枚举名上 */
TYPE,
/** 注解在成员变量上 */
FIELD,
/** 注解在方法名上 */
METHOD,
/** 注解在方法参数上 */
PARAMETER,
/** 注解在构造方法上 */
CONSTRUCTOR,
/** 注解在局部变量 */
LOCAL_VARIABLE,
/** 注解在注解上 */
ANNOTATION_TYPE,
/** 注解在包名上 */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
- @Retention 注解的运行时期
A. SOURCE : 注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
B. CLASS : 注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机中),请注意,当注解未定义Retention值时,默认值是CLASS,如Java内置注解,@Override、@Deprecated、@SuppressWarnning等
C. RUNTIME : 注解信息将在运行期(JVM)也保留,因此可以通过反射信机制读取注解的息(源码、class文件和执行的时候都有注解的信息),如SpringMvc中的@Controller、@Autowired、@RequestMapping等。 - 注解的元素及其类型
String name() default "";
在注解名花括号里的便是注解的元素,它对应的是我们写在@Entity(name="user"),的大括号里面的东西,除了常见的string和int类型,它还可以是以下的几种类型:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Reference{
boolean next() default false;
}
public @interface AnnotationElementDemo {
//枚举类型
enum Status {FIXED,NORMAL};
//声明枚举
Status status() default Status.FIXED;
//布尔类型
boolean showSupport() default false;
//String类型
String name()default "";
//class类型
Class<?> testCase() default Void.class;
//注解嵌套
Reference reference() default @Reference(next=true);
//数组类型
long[] value();
}
元注解(@Target(ElementType.ANNOTATION_TYPE))
刚刚介绍的@Target,@Retention便是元注解,元注解负责注解其他注解,Java还有@Documented 和 @Inherited 两个元注解.
- @Documented 被修饰的注解会生成到javadoc中
- @Inherited 被注解的注解 注解的类,可以被其他类继承,然后注解的特性会转移到子类上,子类Class对象使用getAnnotations()获取父类被@Inherited修饰的注解
Java内置注解(@Retention(RetentionPolicy.RUNTIME))
- @Override:用于标明此方法覆盖了父类的方法
- @Deprecated:用于标明已经过时的方法或类
- @SuppressWarnnings:用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告 比如 :
@SuppressWarnings({"uncheck","deprecation"})
注解与反射
- public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
注解通过反射获取。首先可以通过 对象的getClass()的 isAnnotationPresent() 方法判断它是否应用了某个注解
User user = new User(); //开文那个类
System.out.println(user.getClass().isAnnotationPresent(Entity.class));//运行结果: true
- public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
然后通过 getAnnotation() 方法来获取 Annotation 对象。
User user = new User();
System.out.println(user.getClass().getAnnotation(Entity.class).tableName());//运行结果为user
-
public Annotation[] getAnnotations() {}
或者是 getAnnotations() 方法获取所有的Annotation对象,包括继承的 -
public Annotation[] getDeclaredAnnotations()
获取所有注解对象,不包括继承的
网友评论