最近在看一个同事写的web框架,其中大量使用了annotation,整体上代码给人的感觉十分简洁明了,主要的思路是:将一些业务校验(如:用户权限校验、商品合法性校验)这些通用的业务逻辑抽取出来,构建一些列独立的annotation,然后在页面代码中嵌入这些annotation,结果就会大幅度减少代码量。用同事的一句话说,少得代码才是好的代码。O(∩_∩)O~
以前编码的中很少使用annotation,翻了一下think in java。
主要思路是:
1.编写annotation
2.编写解释器。
3.运行到相关代码的时候使用解释器去解释执行这些代码。
核心思想还是java的反射机制。
废话少说,一个通过annotation自动生成SQL语句的工具,代码如下:
主要包含:
1.基本数据结构annotation,包含了sql中的基本数据结构(demo中包含:int、string类型),包括自动名称、字段长度的等信息,以及新建的表的名字。
2.使用这些annotation构建一个DO对象,对象中的成员变量使用我们自定义的annotation修饰。
3.自定义annotation解释器,对待建表DO中做了annotation声明的成员变量进行解析。
package com.anatation.database;
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 SQLString {
//字段长度
int value() default 0;
//字段名称
String name() default "";
//字段附加属性
Constrains constrains() default @Constrains;
}
package com.anatation.database;
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 SQLInteger {
String name() default "";
Constrains constrain() default @Constrains;
}
package com.anatation.database;
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 Constrains {
boolean primaryKey() default false;
boolean unique() default false;
boolean allowNull() default true;
}
package com.anatation.database;
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 DBTable {
public String name() default "";
}
package annatationTest;
import com.anatation.database.Constrains;
import com.anatation.database.DBTable;
import com.anatation.database.SQLInteger;
import com.anatation.database.SQLString;
@DBTable(name="memeber")
public class Member {
@SQLString(value=30,constrains=@Constrains(allowNull=false)) private String firstName;
@SQLString(10) private String lastName;
@SQLInteger private int age;
@SQLString(value=10, constrains=@Constrains(primaryKey=true,unique=true)) private String handle;
@SQLInteger private int level;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getHandle() {
return handle;
}
public void setHandle(String handle) {
this.handle = handle;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}
package annatationTest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import com.anatation.database.Constrains;
import com.anatation.database.DBTable;
import com.anatation.database.SQLInteger;
import com.anatation.database.SQLString;
public class AnatationTest {
public static void main(String[] args) {
String[] classNames = {"annatationTest.Member"};
try{
for(String className : classNames){
Class cl = Class.forName(className);
DBTable dbTable = (DBTable) cl.getAnnotation(DBTable.class);
if(dbTable == null)
continue;
String tableName = dbTable.name();
if(tableName.length() <= 0){
tableName = cl.getSimpleName();
}
List<String> columnNames = new ArrayList<String>();
for(Field field : cl.getDeclaredFields()){
String columnName = "";
Annotation[] annotations = field.getDeclaredAnnotations();
if(annotations.length <= 0)
continue;
if(annotations[0] instanceof SQLInteger){
SQLInteger tmpSqlInt = (SQLInteger)annotations[0];
columnName = tmpSqlInt.name();
if(columnName.length() <= 0){
columnName = field.getName()+" integer";
}
String constrain = getConstraon(tmpSqlInt.constrain());
columnName += constrain;
}
if(annotations[0] instanceof SQLString){
SQLString tmpSqlStr = (SQLString)annotations[0];
columnName = tmpSqlStr.name();
if(columnName.length() <= 0){
columnName = field.getName();
}if(tmpSqlStr.value() > 0){
columnName += " varchar("+ tmpSqlStr.value()+") ";
}
String constrain = getConstraon(tmpSqlStr.constrains());
columnName += constrain;
}
columnNames.add(columnName);
}
String sqlCreat = "CREATE TABLE "+ tableName +" ( \n";
String createCommond = "";
for(String str : columnNames){
createCommond += str +",\n";
}
sqlCreat += createCommond +" ) ";
System.out.println(sqlCreat);
}
}catch (Exception e) {
System.out.println(e);
}
}
private static String getConstraon(Constrains constrain) {
String rst = "";
if(!constrain.allowNull()){
rst += " NOT NULL ";
}
if(constrain.primaryKey()){
rst += " primarykey ".toUpperCase();
}
if(constrain.unique()){
rst += " unique ".toUpperCase();
}
return rst;
}
}