注解相关:
实现:根据传入的Bean对象来生成并返回相应的查询语句.
//将数据表名和字段名与类名和成员变量名称一一对应起来.
@Table("user")
Class Bean{
@Column("id")
private int id;
@Column("user_name")
private String name;
@Column("phone_number")
private String phone;
@Column("email")
private String email;
@Column("address")
private String address;
//省略了setter / getter方法
}
//自定义注解
@Target({ElementType.Type})
@Retention(RetentionPolicy.RunTime)
public @interface Table{
String value();
}
@Target({ElementType.Field})
@Retention(RetentionPolicy.RunTime)
public @interface Column{
String value();
}
//解析注解.
public Class Test{
public static void main(String[] args){
Bean b1=new Bean();
b1.setId(9);
b1.setName("Manny");
Bean b2=new Bean();
b2.setEmail("liuguoxing888@126.com","554010708@126.com);
String sql1=query(b1);
String sql2=query(b2);
syso(sql1);
syso(sql2);
}
public static String query(Bean b){
StringBuilder sb=new StringBuilder();
//解析Bean类中的注解.[学会如何解析注解是目的]
Class c=b.getClass();
//首先判断标注类名的注解@Table是否存在.
boolean isExist=c.isAnnotationPresent(Table.class);
if(!isExist) return null;
Table table=c.getAnnotation(Table.class);
String table_name=table.value();
sb.append(" select * from ").append(table_name).append(" where 1=1");
//下面获得每一个字段上的注解的值(数据表中每个字段的名称);
Field[] fields=c.getDeclaredFields();
for(Field field:fields){
boolean exists=field.isAnnotationPresent(Column.class);
if(!exists) continue;
Column column=field.getAnnotation(Column.class);
String column_name=column.value();
//得到数据表中每个字段的值
//通过反射,操作getFieldName()方法一获得
String fieldName=field.getName();
String getFieldName=
"get"+fieldName.subString(0,1).toUpperCase+fieldName.subString(1);
Method m=c.getMethod(getFieldName);
Object fieldValue = m.invoke(b);
if(fieldValue==null || (fieldValue instanceof Integer && (int)fieldValue==0){
//当值为null or 0时,
//直接进行下次循环
continue;
}
//判断fieldValue的数据类型.
//还不如直接获得到get方法的返回值类型来的容易!
Class returnType=m.getReturnType();
String type_name=returnType.getSimpleName();
switch(type_name){
case "String":
if(((String)fieldValue).contains(","){
String[] values=((String)fieldValue).split(",");
sb.append(" "+fieldName+" in(");
for(String value:values){
sb.append(value+",");
}
sb.deleteCharAt(sb.length-1);
sb.append(" )");
}else{
sb.append(" "+fieldName+" = "+fieldValue);
break;
case "int":
sb.append(" and "+ fieldName+" = " + (int) fieldValue);
break;
...
}
}
return sb.toString();
}
}
2.注解的好处
.能够读懂别人的代码,尤其是框架相关的代码
.让编程更加简洁,代码更加清晰.(配置文件...)
3.运用自定义注解解决问题.
注解定义: java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法.
Java中自带注解(3个):
@override:指明是覆盖父类或接口中的一个方法.
@deprecated:指明一个方法已经过时了.但是也可以用.
@supressWarnings:指明在某个位置告诉编译器不需要警报.
按照运行机制分为:
源码注解:只存在于源码中
编译时注解:在源码和.class文件中存在.JDK自带的3个都属于编译时注解.
运行时注解:在运行阶段还起作用,甚至会影响运行逻辑.
元注解:注解的注解.@Target({ElementType.METHOD,ElementType.TYPE })
{CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,
PACKAGE,PARAMETER,TYPE}包含了JAVA中所有元素.
@Retention(RetentionPolicy.RUNTIME)
{RetentionPolicy.SOURCE.RetentionPolicy.CLASS}
@Inherited(标识注解).[
@Documented @Retention(value=RUNTIME) @Target(value=ANNOTATION_TYPE) public @interface Inherited
Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses;annotations on implemented interfaces have no effect.
()注解是否可以被当前类的子类继承.这个继承只能对类的继承有效果,除此之外,包括接口的实现同样没有任何效果)
@Documented(标识注解): 表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中.[
@Documented @Retention(value=RUNTIME) @Target(value=ANNOTATION_TYPE) public @interface Documented
[如果只是一个成员,那么就不用写<成员名=>.]
4.注解的解析.[重点!]
通过反射 获取类/函数或成员上 的运行时注解信息,从而实现动态控制程序运行的逻辑.
解析示例见1.
参考:Java反射机制总结(1),源文地址 http://blog.youkuaiyun.com/Mark_LQ/article/details/50085465