簡單的註解剖析

来源:https://www.cnblogs.com/qpf1/archive/2018/06/09/9161690.html
-Advertisement-
Play Games

周邊有許多同事只會使用註解,並不瞭解註解的原理。於是隨手寫一個小Demo,普及下註解的使用原理,順便加深自己的理解。如有錯誤,歡迎大牛指正。 1 註解類基本樣式 2 註解類的元素解析 元註解: 總共有四個元註解,分別是:@Target,@Retention,@Documented,@Inherite ...


  周邊有許多同事只會使用註解,並不瞭解註解的原理。於是隨手寫一個小Demo,普及下註解的使用原理,順便加深自己的理解。如有錯誤,歡迎大牛指正。

1 註解類基本樣式

/**
 *
 * @author qpf
 * 此註解用於對錶名的設置
 *
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}

2 註解類的元素解析

元註解:  
總共有四個元註解,分別是:@Target,@Retention,@Documented,@Inherited,屬於jdk註解,作用如下:       @Target 表示該註解用於什麼地方,可能的值在枚舉類 ElemenetType 中,包括:            ElemenetType.CONSTRUCTOR----------------------------構造器聲明            ElemenetType.FIELD --------------------------------------域聲明(包括 enum 實例)            ElemenetType.LOCAL_VARIABLE------------------------- 局部變數聲明            ElemenetType.METHOD ----------------------------------方法聲明            ElemenetType.PACKAGE --------------------------------- 包聲明            ElemenetType.PARAMETER ------------------------------參數聲明            ElemenetType.TYPE--------------------------------------- 類,介面(包括註解類型)或enum聲明                   @Retention 表示在什麼級別保存該註解信息。可選的參數值在枚舉類型 RetentionPolicy 中,包括:            RetentionPolicy.SOURCE ---------------------------------註解將被編譯器丟棄            RetentionPolicy.CLASS -----------------------------------註解在class文件中可用,但會被VM丟棄            RetentionPolicy.RUNTIME -------將在運行期也保留註釋,因此可以通過反射機制讀取註解的信息。  @Documented 將此註解包含在 javadoc 中 ,它代表著此註解會被javadoc工具提取成文檔。在doc文檔中的內容會因為此註解的信息內容不同而不同。相當與@see,@param 等。  @Inherited 允許子類繼承父類中的註解。
    註解使用方法:
@Table("StudentInfo")
public class StudentInfo extends BaseTable
{
     //學生姓名
     @Column("name")
     private String name;
     
     //性別
     @Column("sex")
     private String sex;
}
  註意:@Target設置了註解放在什麼地方,設置為ElemenetType.FIELD,則需要將註解放置在屬性的上方。設置為ElemenetType.TYPE,則需要放置在class上方。放錯位置,編譯器會報錯。 原理:把public @interface Table {String value();}和@Table("StudentInfo") 放在一起看,其實註解就是返回你所設置的指定類型的值。其實就是在調用註解的value()方法,會返回String類型的值,值為註解中設置的“StudentInfo”。後面例子中會有詳細介紹。還需註意一點,註解中返回的類型是有限定的,且方法一定要是無參的,不懂的可自行百度。  

3 利用註解實現小Demo

3.1 需求內容

1、有一張學生信息表,欄位包括姓名,年級,班級,教師名,性別等;

2、利用註解,對錶實例的每個欄位進行檢查,並列印出查詢sql   

3.2 代碼結構

annotation:存放創建的註解。 bean:存放資料庫表所用到的javaBean test:main函數,用於測試並列印查詢sql;  

3.3 註解類

/**
 *
 * @author qpf
 * 此註解用於對錶欄位的設置
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}

 

/**
 *
 * @author qpf
 * 此註解用於對錶名的設置
 *
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}

 

3.4 學生信息表的javabean

下麵的代碼刪去了get和set方法。

/**
 *
 * @author qpf
 * Table標簽里為表名
 * Column標簽里為資料庫欄位名
 */
@Table("StudentInfo")
public class StudentInfo extends BaseTable
{
     //學生姓名
     @Column("name")
     private String name;
     
     //性別
     @Column("sex")
     private String sex;
     
     //年級
     @Column("grade")
     private String grade;
     
     //班級
     @Column("class_num")
     private String classNum;
     
     //班主任
     @Column("teacher")
     private String teacher;
     
     //總分
     @Column("total_scores")
     private String totalScores;
     
     //微信號
     @Column("weChat_num")
     private String weChatNum;
     
     //手機號
     @Column("tel_num")
     private String telNum;
     
     //父親名
     @Column("father_name")
     private String fatherName;
     
     //母親名
     @Column("mother_name")
     private String motherName;
}
 

  

3.5 AnnotationTest方法

public class AnnotationTest {
     /**
      * 需求設計:
      *    1、有一張學生信息表,欄位包括姓名,年級,班級,教師名,性別等;
      *    2、利用註解,對每個欄位的組合條件進行檢查,並列印出sql     
      */
     public static void main(String[] args)
     {
         // TODO Auto-generated method stub
         StudentInfo studentInfo=new StudentInfo();
         studentInfo.setName("Tom");
         studentInfo.setSex("men");
         studentInfo.setTelNum("18255005147,18255005148,18255005149");
         studentInfo.setWeChatNum("qpf123456");
         String sql=querySql(studentInfo);
         System.out.println((sql==null)?"":sql);
     }
     public static String querySql(BaseTable table)
     {
         //獲取類載入器
         Class<?> cTable=table.getClass();
         //判斷類中是否包含Table的註解
         boolean tableIsExists=cTable.isAnnotationPresent(Table.class);
         
         //判斷是否為表實例
         if(!tableIsExists)
         {
              return null;
         }
         
         //獲取表名
         String tableName=cTable.getAnnotation(Table.class).value();
         
         //初始化表查詢語句
         StringBuilder builder=new StringBuilder("select * from");
         builder.append(" "+tableName+" where 1=1");
         
         //獲取表實例中的所有欄位
         Field[] fields=cTable.getDeclaredFields();
         
         
         try
         {
              for (Field field : fields)
              {
                   //判斷是否為表數據欄位
                boolean columnIsExist=field.isAnnotationPresent(Column.class);
                   
                   if(!columnIsExist)
                   {
                       continue;
                   }
                   
                   //判斷表數據欄位的值是否為null
                   field.setAccessible(true);
                   String fieldValue=(String)field.get(table);
                   if(null==fieldValue || "".equals(fieldValue))
                   {
                       continue;
                   }
                   
                   //檢測到需要拼接欄位時,再獲取資料庫欄位名
                   String columnName=field.getAnnotation(Column.class).value();
                   
                   //需要用in的欄位處理
                   if(fieldValue.contains(","))
                   {
                       builder.append(" and "+columnName+" in(");
                       String[] strs=fieldValue.split(",");
                       
                       for (int i = 0; i < strs.length; i++)
                       {
                            builder.append("'"+strs[i]+"'");
                            if(i!=strs.length-1)
                            {
                                 builder.append(",");
                            }
                       }
                            
                       builder.append(")");
                   }
                   else
                   {
                    builder.append(" and "+columnName+"="+"'"+fieldValue+"'");
                   }
                   
              }
         }
         catch (Exception e)
         {
              // TODO Auto-generated catch block
              e.printStackTrace();
         }
         
         return builder.toString();
     }
}

  

上面方法列印出的查詢sql語句為:

select * from StudentInfo where 1=1 and name='Tom' and sex='men' and weChat_num='qpf123456' and tel_num in('18255005147','18255005148','18255005149')

  

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 幾年以來都是看著人家的博客,現在也嘗試著去自己整理。第一次博客簡單,勿噴。。。 ...
  • name = 'MyName' age = 32 print('我的名字是%s,年齡是%d,輸出百分號%%' %(name,age)) a = 10 b = 12 if a>b: print(a) else: print(b) ...
  • 本節內容   Django流程介紹 Django url Django view Django models Django template Django form Django admin    Django流程介紹     Django URL ...
  • 備註:本文引用自《深入理解Java虛擬機第二版》 2.1 運行時數據區域 Java虛擬機在執行Java程式的過程中把它所管理的記憶體劃分為若幹個不同的數據區域。這些區域都有各自的用途,以及創建和銷毀的時間,有的區域隨著虛擬機進程的啟動而存在,有些區域則依賴用戶線程的啟動和結束而建立和銷毀。如下圖所示: ...
  • Java的繼承初始化順序 當使用繼承這個特性時,程式是如何執行的; ...
  • 前段時間發現項目中的上傳FTP軟體有可能會在從伺服器申請斷連時Crash, 所以加了一個Timer。 由於項目代碼行數過大, 此處上傳部分代碼片段。 在此進程發出MesUPLOADTimeout 信息之後, 項目主進程會從代理Proxy中接受此信息併進行處理。 主進程重啟上傳軟體,從而跳過斷連。 ...
  • 最近在搞kettle整合kafka producer插件,於是自己搭建了一套單機的kafka環境,以便用於測試。現整理如下的筆記,發上來和大家分享。後續還會有kafka的研究筆記,依然會與大家分享! 1 kafka環境搭建 1.1 kafka單機環境搭建 (1)、解壓kafka_2.11-1.1.0 ...
  • java 數據類型:基本類型與引用類型 基本類型:數值型,其中數值型分為整型、浮點型,整型包括 byte、short 、int、long ,預設為 int 類型。浮點類型分為單精度、雙精度,分為 float、double ,預設為 double 類型。註意各種類型所占用空間大小。 除數值型,還包括 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...