java註解簡單講解及應用

1、java中常見的註解


jdk自帶的註解:
                @Override    覆蓋父類方法


	        @Override
	        public String name() {
		return null;
	           }

當發現父類的方法定義的有些問題,但是又不能刪除,因爲有些地方還在
調用這個接口則:


                @Deprecated   表示方法已經過時


父類中設置方法過時:
          	@Deprecated
	        public void sing();

                @Suppvisewarnings  忽視方法過時的警告

當測試類調用時,會出現方法過時的警告,點擊感嘆號,添加忽視過時:
                @SuppressWarnings("deprecation")
	        public void sing(){
		Person p = new child();
		p.sing();
	                 }



2、常見的第三方註解:


Spring :


                @Autowired

                @Service

                @Repository

Mybatis :
 
                @InterProvider

                @UpdateProvider
          
                @Options
              
  
3、註解的分類:


                -->源碼註解
                註解只在源碼中存在,編譯成.class文件就沒了


                -->編譯時註解
                註解在源碼和.class文件中存在
                例如:@Override告訴編譯器覆蓋父類方法,然後進行編譯


                -->運行時註解
                註解在運行階段還起作用,影響運行邏輯          
                例如:@Autowired運行時把成員變量裝配進來


                元註解:給註解進行的註解




4、自定義註解:


   聲明:
      @Target({ElementType.METHOD,ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Inherited
      @Documented
      public @interface Description{// 使用@interface關鍵字定義注 


                                      解
        String desc();//成員以無參無異常方式聲明


        String author();


        int age() default 18;//可以用default爲成員指定一個默認值


        }




    元註解:
      //註解作用域(構造方法、局部變量、方法聲明、包聲明類接口等)
      @Target({ElementType.METHOD,ElementType.TYPE})
      //註解的生命週期(源碼、編譯時、運行時)
      @Retention(RetentionPolicy.RUNTIME)
      //表示註解允許子類繼承
      @Inherited
      //表示生成javadoc時會包含註解
      @Documented



    使用自定義註解:
      @Description(desc="zy",author="boy",age=18)
      public String eyeColor(){
           return "red";
            }
    這樣,@Description註解就在eyeColor()方法上使用


5、解析註解:


   通過反射獲取類、函數或成員上的運行時註解信息,從而動態控制程序 


  運行的邏輯.


   	//1、使用類加載器加載類
		 try {
			Class c = Class.forName


("com.ann.test.child");
			//2、找到類上面的註解(判斷指定類上是否存


在Description這個註解)
			boolean isExist = c.isAnnotationPresent


(Description.class);
			if(isExist){
				//3、拿到註解實例
				Description d = (Description)


c.getAnnotation(Description.class);
				System.out.println(d.value());
			}
			//4、找到方法上的註解
			  //首先遍歷所有的方法
			   Method[] ms = c.getMethods();
			   for (Method m : ms) {
				   //判斷是否有註解
				boolean isMExist = 


m.isAnnotationPresent(Description.class);
				if (isMExist) {
					//如果存在則使用註解
					Description md = 


(Description)m.getAnnotation(Description.class);
					System.out.println


(md.value());
				}
				
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		




     註解的繼承:


          父類中添加註解,子類中刪除原有註解
          此時還是用上面的解析方式對子類進行註解解析

          此時運行不輸出任何東西

          原因是:  @Inherited對於接口繼承不起作用
          所以要把Person改爲類,而不是接口
          child類中改爲extends
          運行 --> 打印出類上的註解,而不打印方法上的註解
          所以註解只繼承類上的註解,而不繼承方法上的註解




6、項目實現:


需求:對象設置好要查詢的條件,調用query()後返回對應的sql語句


Filter.java類:(對應了數據庫表中各個字段)

   
   package com.zy.test;


@Table("user")
public class Filter {


   @Column("id")	
   private int id;
   
   @Column("user_name")	
   private String userName;
   
   @Column("nick_name")	
   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 nickNameString) {
	this.nickName = nickNameString;
}




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




Test實現類:(實現配置好查詢條件,調用query返回sql)


package com.zy.test;

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的用


戶
		
		Filter f3 = new Filter();
		f3.setEmail


("[email protected],[email protected],[email protected]");//查詢郵箱爲其中任意一個


的用戶
		
		//調用query進行查詢
		String sql1 = query(f1);
		String sql2 = query(f2);
		String sql3 = query(f3);
		
		System.out.println(sql1);
		System.out.println(sql2);
		System.out.println(sql3);
		
	
	}
	
	private static String query(Filter f){
		return null;
	}


}





對Filter類進行添加@Table和@Column兩個註解之後,接下來對這兩個註解
進行定義:(這裏定義註解將對象與數據庫中的表對應起來)


Table.java:(設置一個參數爲表名,作用域爲類或接口)
Column.java:(設置一個參數爲列名,作用域爲參數)
 


package com.zy.test;


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



package com.zy.test;


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


Test.java中query()方法的實現:(注意這裏字段值有String和int類型,所以要定義爲 Object類型)
   
      
package com.zy.test;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;




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(19);
		
		Filter f3 = new Filter();
		f3.setEmail


("[email protected],[email protected],[email protected]");//查詢郵箱爲其中任意一個


的用戶
		
		//調用query進行查詢
		String sql1 = query(f1);
		String sql2 = query(f2);
		String sql3 = query(f3);
		
		System.out.println(sql1);
		System.out.println(sql2);
		System.out.println(sql3);
		
	
	}
	
	private static String query(Filter 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 ");
		 //遍歷所有的字段
		Field[] fArray = c.getDeclaredFields();
	    for (Field field : fArray) {
			//4.處理每個字段對應的sql
	    	//4.1 拿到字段名
	    	boolean fExists = field.isAnnotationPresent


(Column.class);
	    	if (!fExists) {//如果不是數據庫字段
				continue;
			}
	    	Column column = (Column)field.getAnnotation


(Column.class);
	    	String columnNameString = column.value();
	    	//4.2 拿到字段的值(通過反射取得get方法的名字,然


後通過反射區調用這個方法,就取得字段值)
	    	String filedName = field.getName();
	    	    //把get加上字段名首字母大寫


filedName.substring(0, 1).toUpperCase(),把首字母之後的名字內容拼


裝上filedName.substring(1),就拼裝成get方法
	    	String getMethodName = "get" + 


filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
	    	    //通過反射獲取對應方法
	    	Object fieldValue = null;
	    	try {
				Method getMethod = c.getMethod


(getMethodName);
				//反射調用此方法後獲得字段值
			    fieldValue = getMethod.invoke(f);
			} catch (Exception e) {
				e.printStackTrace();
			}
	    	//拼裝sql
	    	//如果字段值爲空或者字段值在int類型時爲0 


fieldValue instanceof Integer && (Integer)fieldValue == 0,將不作


處理
	    	if (fieldValue == null || (fieldValue instanceof 


Integer && (Integer)fieldValue == 0)) {
				continue;
			}
	    	sb.append("and ").append(filedName);
	    	if (fieldValue instanceof String) {
	    		//如果是包含三個郵箱的查詢,即包含逗號
	    		if (((String) fieldValue).contains(",")) 


{
					String[] value = 


((String) fieldValue).split(","); 
					sb.append("in(");
					for (String v : value) {
						sb.append


("'").append(v).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();
		 
	}


}


現在如果有第二張表(Department.java),也需要這樣的方式進行sql生成
則只需要在對應對象中添加@Table和@Column註解即可


Department.java:


package com.zy.test;


@Table("department")
public class Department {


   @Column("id")	
   private int id;
   
   @Column("name")	
   private String name;
   
   @Column("leader")	
   private String leader;
	
   @Column("number")	
   private int number;


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 getNumber() {
	return number;
}


public void setNumber(int number) {
	this.number = number;
}
   
   
}



只需要把query()方法中參數改爲Object,這樣就所有對象添加了註解的都有效了


	Department d = new Department();
		d.setId(1);
		d.setLeader("kkk");
		d.setNumber(111);
		System.out.println(query(d));

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章