注解:Java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法
JDK自带注解
@Override 标识该方法是覆盖了父类中的方法
@Deprecated 标识该方法已过时
@Suppvisewarnings 忽略某种警告
自定义注解:
- 使用@interface关键字定义注解
- 成员以无参无异常方式声明
- 可以用default为成员指定一个默认值
- 成员的类型是受限的,合法的类型包括原始类型及String、Class、Annotation、Enumeration
- 如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号=
也可以没有成员,此时为标识注解,例如Override就是一个标识注解
@Target({ElementType.*}) 注解的作用域
参数:
CONSTRUCTOR 构造方法声明
FIELD 字段声明
LOCAL_VARIABLE 局部变量声明
METHOD 方法声明
PACKAGE 包声明
PARAMETER 参数声明
TYPE 类接口
@Retention(RetentionPolicy.*) 注解的生命周期
参数:
SOURCE 只在源码显示,编译时会丢弃
CLASS 编译时会记录到class中,运行时忽略
RUNTIME 运行时存在,可以通过反射读取
@Inherited 允许子类继承,只会继承父类的类上的注解,而不会继承父类中的方法上的注解
@Documented 生成javadoc时会包含注解
eg1:
/*注解类*/
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;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Describe {
String value();
}
@Describe("I am class annotation")
public class Child implements Person{
@Override
@Describe("I am method annotation")
public String name() {
// TODO Auto-generated method stub
return null;
}
@Override
public int age() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void sing() {
// TODO Auto-generated method stub
}
}
通过反射解析Child类,来获取Child类中的注解
public class ParseAnno {
public static void main(String[] args) {
try {
Class c=Class.forName("com.lmr.annotation.Child");
//获取类上的注解
Boolean cflag=c.isAnnotationPresent(Describe.class);
if(cflag){
Describe d=(Describe) c.getAnnotation(Describe.class);
System.out.println(d.toString()+" - - "+d.value());
}
//获取方法上的注解
Method[] ms=c.getMethods();
for(Method m:ms){
Boolean mflag=m.isAnnotationPresent(Describe.class);
if(mflag){
Describe d=m.getAnnotation(Describe.class);
System.out.println(d.toString()+" - - "+d.value());
}
}
for(Method m:ms){
Annotation[] as=m.getAnnotations();
for(Annotation a:as){
if(a instanceof Describe){
Describe d=(Describe) a;
System.out.println(d.toString()+" - - "+d.value());
}
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:将类中的注解和方法上的注解打印出来
@com.lmr.annotation.Describe(value=I am class annotation) - - I am class annotation
@com.lmr.annotation.Describe(value=I am method annotation) - - I am method annotation
@com.lmr.annotation.Describe(value=I am method annotation) - - I am method annotation
eg2:通过注解和反射来拼接sql语句
/*表名*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Table {
String value();
}
/*字段名*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Column {
String value();
}
/*Bean类*/
@Table("Person")
public class SqlPerson {
@Column("Id")
private int id=-1;
@Column("Name")
private String name;
@Column("Age")
private int age=-1;
@Column("City")
private String city;
@Column("Email")
private String email;
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 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;
}
}
通过反射解析Bean类上面的注解,来获取其在数据库中的表名和字段名,并获取该字段变量的值,从而来拼接对应的sql语句
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class SqlAnno {
public static void main(String[] args) {
SqlPerson sp1=new SqlPerson();
sp1.setName("Jack");
sp1.setAge(18);
SqlPerson sp2=new SqlPerson();
sp2.setId(1);
sp2.setName("Jane");
sp2.setEmail("123456789@qq.com");
String sql1=QuerySql(sp1);
System.out.println(sql1);
String sql2=QuerySql(sp2);
System.out.println(sql2);
}
private static String QuerySql(SqlPerson sp) {
// TODO Auto-generated method stub
StringBuilder sb=new StringBuilder();
sb.append("select * from ");
try {
Class c=Class.forName("com.lmr.annotation.SqlPerson");
//获取类上的注解,得到表名
Boolean cflag=c.isAnnotationPresent(Table.class);
if(cflag){
Table table=(Table) c.getAnnotation(Table.class);
sb.append(table.value());
}
sb.append(" where 1=1 ");
//获取Bean类中的所有字段
Field[] fs=c.getDeclaredFields();
for(Field f:fs){
//获取字段上的注解,得到表中的字段名
String columnname = null;
Boolean fflag=f.isAnnotationPresent(Column.class);
if(fflag){
Column column=f.getAnnotation(Column.class);
columnname=column.value();
}
//获取该字段的get方法
PropertyDescriptor pd=new PropertyDescriptor(f.getName(), c);
Method getmethod=pd.getReadMethod();
//获取该字段的值
Object data=getmethod.invoke(sp);
// f.setAccessible(true);
// Object data=f.get(sp);
//获取该字段的类型
String type=pd.getPropertyType().getSimpleName();
//拼接sql语句
if(type.equals("int")&&Integer.parseInt(data.toString())!=-1){
sb.append("and "+columnname+"="+data+" ");
}else if(type.equals("String")&&data!=null){
sb.append("and "+columnname+"=\""+data+"\" ");
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return sb.toString();
}
}
结果:
select * from Person where 1=1 and Name="Jack" and Age=18
select * from Person where 1=1 and Id=1 and Name="Jane" and Email="123456789@qq.com"