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());
}
}
}
}
}