Java 注解可以理解为元数据,所谓元数据即是描述数据的数据,如我们平时用的hibernate,就可以注解的方式描述model信息:
@Entity
@Table(name="teams")
public class Team {
@Id
@GeneratedValue
private Integer id;
@Column(nullable = false)
private String name;
private Integer rating;
}
通过注解,指定实体类Team与teams 呈映射关系,并且id为表的主键,表中name列不能为null。这些也可以通过xml文件配置,那么相比于xml文件,两者有什么区别吗?举一个例子,我们使用SpringMVC开发WebApp的时候,常有一个application.xml文件,配置sessionFactory,transactionManager这些通用的组件,这部分组件不和任何特定的代码相关联;而一些Controller,Service,则通过注解(@Conroller,@Service)的形式配置,因为这部分代码与注解中的信息紧密耦合,这增强了代码的可读性。
自定义注解是比较简单的,与定义接口非常类似:
如上面@Column的定义:
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Column {
String name() default "";
boolean unique() default false;
boolean nullable() default true;
boolean insertable() default true;
boolean updatable() default true;
String columnDefinition() default "";
String table() default "";
int length() default 255;
int precision() default 0;
int scale() default 0;
}
自定义注解需要使用以下注解:
@Documented – 表示在生产 JavaDoc 文档的时候把注解信息也包含进去
@Retention – 表示该注解的级别。可选的范围有:
SOURCE : 只在源代码里出现,编译后就被丢弃了,如@Override, @SuppressWarnings
CLASS : 会被编译到 class 文件里。
RUNTIME : 在 JVM 加载 class 文件的时候,也会把注解的信息加载进去,
可用于运行时反射,自定义注解时常用的级别。
@Target – 表示该注解的作用位置
@Inherited – 表示子类运行继承父类的注解。
记住,注解仅仅是元数据(为类,方法,字段,包提供信息),它本身并不包含任何的业务逻辑,通常另有一块代码来读取注解中的信息,处理相应的业务逻辑。
请看示例:
注解的定义:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TInfo {
String fieldName() default "";
}
注解的使用:
public class Item {
private int id;
@TInfo(fieldName="商品名称")
private String name;
@TInfo(fieldName="商品数据")
private int count;
}
注解的处理类(需要使用反射):
public class Consumer {
public static void annoInfo(Class<?> clazz){
Field[] fields = clazz.getDeclaredFields();// 得到指定类的所有属性Field.
// 打印注解信息
for (Field field : fields) {
if (field.isAnnotationPresent( TInfo.class)) {
System.out.println(field
.getAnnotation(TInfo.class).fieldName());
}
}
}
public static void main(String[] args){
annoInfo(Item.class);
}
}