Java註解簡介、自定義註解及模擬Junit、模擬hibernate根據實體類建表

註解簡介

註解:JDK1.5的新特性

註解(也被稱爲元數據)爲我們在代碼中添加信息提供了一種形式化的方法,使我們可以在稍後某個時刻非常方便地使用這些數據。

Java SE5 三個內置標準註解

  • @Override:方法覆蓋、重寫;
  • @Deprecated:過時的;
  • @SupperessWornings:關閉不當的編譯器警告信息;

元註解:

  • @Target:表示註解在什麼地方使用,可用ElementType,其值爲:
    * constructor:說明該方法用在構造方法上;
    * field:說明蓋註解用在屬性上;
    * local_variable:局部變量上;
    * method:用在方法上;
    * package:用在包聲明上;
    * parameter:用在參數上;
    * type:用在類或接口上;

  • @Retention:表示需要在什麼級別保存該註解信息,可能的參數值RetentionPolicy爲:
    source:表示該註解會被編譯器丟棄
    class:說明該註解會在.class文件中,但會被JVM丟棄
    runtime:jvm將在運行期間保留,因此可以通過反射機制來讀取註解信息

  • @Documented:將該註解包含在JavaDoc中。表示此註解會被javadoc工具提取成文檔。

  • @Inherited:允許子類繼承父類中的註解。

自定義註解

  1. 定義註解
import java.lang.annotation.*;
@Target(ElementType.METHOD)		//說明此註解用在方法上
@Retention(RetentionPolicy.RUNTIME)		//說明是運行級別
public @interface Info {
	int id();			//爲區分接口與類,在後面加上()
	String des() default "暫無信息";
}
  1. 定義目標類
public class TestInfo {
	@Info(id=1,des="show方法")
	public void show() {
		System.out.println("陰雨綿綿。。。");
	}
	@Info(id=2)
	public String getInfo() {
		return "欸。。。";
	}
	public void description(){
		System.out.println("真是應景。。。");
	}
}
  1. 定義測試類
public class InfoTracker {
	public static void main(String[] args) {
		test(TestInfo.class);
	}
	public static void test(Class<TestInfo> cl) {
		Info info = null;
		for( Method method : cl.getDeclaredMethods() ){	//循環給定類中的所有方法。也可以給定包路徑,自動掃描該包下的所有類
			if( method.isAnnotationPresent( Info.class ) ){
				//method.getAnnotations();	//獲取這個方法上的所有註解
				
				//現在我們只想知道是否有我們給定的註解Info
				System.out.println( method.getName() + "有Info註解" );
				
				info = method.getAnnotation(Info.class);
				System.out.println(info.id() + "-" + info.des());
			}else{
				System.err.println( method.getName() + "沒有Info註解" );
			}
		}
	}
}

Java註解模擬實現Junit

  1. 創建註解類
import java.lang.annotation.*;

@Target(value={ElementType.METHOD})		//目標:作用域方法		//兩種寫法
@Retention(RetentionPolicy.RUNTIME)		//保留範圍:運行時保留,不會被jvm丟棄
public @interface Beta {
	//這個註解類中不需要任何屬性
}
  1. 編寫測試用例類
public class Test {
	@Beta	//加上自定義的測試註解
	public void test(){
		System.out.println("SUCCESS!");
	}
	@Beta
	public void test2(){
		System.out.println("成功了!哈哈哈...");
	}
	@Beta
	public void test3(){
		System.err.println("嘻嘻嘻...");
	}
}
  1. 編寫註解方法的操作測試類
public class TestBeta {
	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
		Class clazz = Test.class;
		
		Method[] methods = clazz.getMethods();
		if(methods != null){
			for(Method method : methods){
				boolean isAP = method.isAnnotationPresent(Beta.class);
				if(isAP){
					method.invoke(clazz.newInstance(), null);
				}
			}
		}
	}
}

註解模擬Hibernate中根據實體類在數據庫建表的方法

  1. 創建用來指定表名的註解
import java.lang.annotation.*;
@Target(ElementType.TYPE)		//說明作用在類上
@Retention(RetentionPolicy.RUNTIME)	//運行時級別
public @interface TableName {
	public String name() default "";
}
  1. 創建用來指定類型的註解
import java.lang.annotation.*;
@Target(ElementType.FIELD)		//說明用在屬性上
@Retention(RetentionPolicy.RUNTIME)
public @interface Type {
	public String type() default "varchar(20)";
	public Constraints constraints() default @Constraints;
}
  1. 創建指定約束的註解
@Target(ElementType.FIELD)		//說明在屬性上
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
	public boolean primaryKey() default false;	//是否爲主鍵
	public boolean allowNull() default true;	//是否可爲空
	public boolean unique() default false;		//是否唯一
	public boolean identity() default false;	//是否自增
}
  1. 創建實體類
@TableName
public class StuInfo {
	@Type(type="int" ,constraints=@Constraints(primaryKey=true,identity=true))
	private int usid;
	
	@Type(type="varchar(200)" ,constraints=@Constraints(allowNull=false,unique=true))
	private String sname;
	
	@Type(type="int")
	private int age;
	
	@Type(constraints=@Constraints(unique=true))
	private String tel;
	public int getUsid() {
		return usid;
	}
	public void setUsid(int usid) {
		this.usid = usid;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
}
  1. 創建測試類
public class TableCreator {
	public static void main(String[] args) {
		TableCreator tc = new TableCreator();
		tc.run();
	}
	static{
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public void run(){
		Connection con = null;
		Statement stmt = null;
		try {
			con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","數據庫用戶名","密碼");
			stmt = con.createStatement();
			String sql = this.getSql(StuInfo.class);
			System.out.println(sql);
			stmt.execute(sql);	//執行sql
			System.out.println("創建成功");
		} catch (Exception e) {
			System.err.println("創建失敗");
			e.printStackTrace();
		}finally {
			try {
				if(stmt != null){
					stmt.close();
				}
				if( con != null ){
					con.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	//建表語句
	public String getSql(Class<?> cl){
		TableName tn = cl.getAnnotation(TableName.class);
		if(tn == null){
			return null;
		}
		String tableName = tn.name();
		if( tableName == null || "".equals(tableName) ){
			tableName = cl.getSimpleName();	//這裏不要使用getName(),那樣會返回帶有包路徑的字符串值
		}
		//如果需要考慮性能,建議使用StringBuffer
		StringBuffer sbf = new StringBuffer();
		sbf.append("create table ").append(tableName).append("(");
		//拼接列  ->  獲取這個對象中的所有屬性  ->  判斷屬性上是否有Type註解
		Field[] fields = cl.getDeclaredFields();
		if(fields == null || fields.length <= 0){
			return null;
		}
		Type type = null;
		for( Field field : fields ){
			type = field.getAnnotation(Type.class);
			if(type != null){
				sbf.append( field.getName() ).append(" ").append( type.type() );
				//這個列上的約束
				if( type.constraints().primaryKey() ){	//如果是主鍵
					sbf.append(" primary key");
					if( type.constraints().identity() ){//則需要判斷是否自增
						sbf.append(" auto_increment");
					}
				}else{//不是主鍵,判斷是否可爲空,是否唯一
					if( !type.constraints().allowNull() ){	//不可爲空
						sbf.append(" not null");
					}
					if( type.constraints().unique() ){	//唯一
						sbf.append(" unique");
					}
				}
				sbf.append(",");
			}
		}
		String sql = sbf.toString();
		//處理最後一個多餘的逗號,並加上反括號
		sql = sql.substring(0,sql.lastIndexOf(",")) + ")";
		return sql;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章