0x6 Java系列Java注解詳解

      網(wǎng)友投稿 617 2025-03-31

      在使用SpringBoot作為Web敏捷開(kāi)發(fā)的框架之后,SpringBoot除了自動(dòng)裝配配置的便捷之外,在很多時(shí)候需要基于注解來(lái)開(kāi)發(fā)。注解不僅增加了代碼的可讀性,還增加了開(kāi)發(fā)的速度。這篇文章主要講述Java?注解。


      元注解

      元注解用于注解其他注解的。Java 5.0定義了4個(gè)標(biāo)準(zhǔn)的元注解,如下:

      ·??????@Target

      ·??????@Retention

      ·??????@Documented

      ·??????Inherited

      現(xiàn)在來(lái)說(shuō)說(shuō)這四個(gè)元注解有什么作用。

      @Target

      @Target注解用于聲明注解的作用范圍,例如作用范圍為類、接口、方法等。它的取值以及值所對(duì)應(yīng)的范圍如下:

      ·??????CONSTRUCTOR:用于描述構(gòu)造器

      ·??????FIELD:用于描述域

      ·??????LOCAL_VARIABLE:用于描述局部變量

      ·??????METHOD:用于描述方法

      ·??????PACKAGE:用于描述包

      ·??????PARAMETER:用于描述參數(shù)

      ·??????TYPE:用于描述類、接口(包括注解類型)?或enum聲明

      @Retention

      該注解聲明了注解的生命周期,即注解在什么范圍內(nèi)有效。

      ·??????SOURCE:在源文件中有效

      ·??????CLASS:在class文件中有效

      ·??????RUNTIME:在運(yùn)行時(shí)有效(即運(yùn)行時(shí)保留)

      大多數(shù)注解都為RUNTIME

      @Documented

      是一個(gè)標(biāo)記注解,有該注解的注解會(huì)在生成java?文檔中保留。

      @Inherited

      該注解表明子類是有繼承了父類的注解。比如一個(gè)注解被該元注解修飾,并且該注解的作用在父類上,那么子類有持有該注解。如果注解沒(méi)有被該元注解修飾,則子類不持有父類的注解。

      自定義注解

      在Java開(kāi)發(fā)者,JDK自帶了一些注解,在第三方框架Spring ?帶了大量的注解,這些注解稱為第三方注解。在很多實(shí)際開(kāi)發(fā)過(guò)程中,我們需要定義自己的注解。那么現(xiàn)在以案例的方式來(lái)講解自定義注解。

      在注解中,需要使用四種元注解來(lái)聲明注解的作用范圍、生命周期、繼承,是否生成文檔等。另外在注解中也可以有自己的成員變量,如果一個(gè)注解沒(méi)有成員變量則稱為標(biāo)記注解。注解的成員變量,只支持原始類型、Class、Enumeration、Annoation。

      現(xiàn)在定義一個(gè)@Writer注解,該注解被Retention、Documented、Inherited、Target修飾,表明該注解的作用范圍為類、接口和方法,生命周期為運(yùn)行時(shí)、該注解生成文檔,并且子類可繼承該注解。該注解有2個(gè)成員變量,一個(gè)為name一個(gè)為age,代碼如下:

      @Retention(RetentionPolicy.RUNTIME)

      @Documented

      @Inherited

      @Target({ElementType.TYPE,ElementType.METHOD})

      public?@interface?Writer?{

      String?name();

      int?age();

      }

      那么有了該注解,怎么用呢?

      該注解的作用范圍為類、方法,寫一個(gè)WriterTest,代碼如下:

      @Writer(name?=?"forezp",?age?=?12)

      public?class?WriterTest?{

      @Writer(name?=?"miya",?age?=?10)

      public?void?writeBlog()?{

      System.out.println("writing?blog");

      }

      }

      該類有了這個(gè)注解有何用?

      一般來(lái)說(shuō),用該類修飾的類,需要通過(guò)反射來(lái)做一下邏輯的開(kāi)發(fā)的工作,可廣泛用于AOP、程序的配置等。現(xiàn)在寫一個(gè)方法通過(guò)反射來(lái)解析該注解:

      public?static?void?main(String[]?args)?throws?ClassNotFoundException?{

      Class?c?=?Class.forName("com.forezp.annotation.WriterTest");

      if?(c.isAnnotationPresent(Writer.class))?{

      Writer?w?=?(Writer)?c.getAnnotation(Writer.class);

      System.out.println("name:"?+?w.name()?+?"???age:"?+?w.age());

      }

      Method[]?methods?=?c.getMethods();

      for?(Method?method?:?methods)?{

      if?(method.isAnnotationPresent(Writer.class))?{

      Writer?w?=?method.getAnnotation(Writer.class);

      System.out.println("name:"?+?w.name()?+?"???age:"?+?w.age());

      }

      }

      }

      這些代碼基本為反射的內(nèi)容,因?yàn)榉瓷湓诹硪黄恼乱呀?jīng)詳細(xì)講述過(guò),不再重復(fù),運(yùn)行該Main方法,控制臺(tái)打印出如下內(nèi)容:

      name:forezp ? age:12

      name:miya ? age:10

      案例實(shí)戰(zhàn)

      有了上述的講解,你可能對(duì)注解有所了解,但是對(duì)注解的具體應(yīng)用并不是很深刻。現(xiàn)在以一個(gè)案例來(lái)詳細(xì)講述。

      大家都對(duì)ORM框架Mybitis都非常的熟悉,在這個(gè)框架中用了大量的注解。現(xiàn)在模仿這個(gè)框架,通過(guò)自定義注解,來(lái)解析sql?的查詢語(yǔ)句。實(shí)現(xiàn)過(guò)程大概如下:

      ·??????定義@Table @Colum注解

      ·??????定義一個(gè)實(shí)體User,定義一些基本的字段,并用注解修飾

      ·??????用User類new對(duì)象,給對(duì)象的某些字段賦值

      ·??????通過(guò)反射和注解來(lái)生成sql?的查詢語(yǔ)句

      首先定義個(gè)一個(gè)Table注解,它的作用范圍為類,代碼如下:

      @Retention(RetentionPolicy.RUNTIME)

      @Target(ElementType.TYPE)

      @Documented

      @Inherited

      public?@interface?Table?{

      String?value()?default?"";

      }

      定義一個(gè)Column注解,作用范圍為字段,代碼如下:

      @Target(ElementType.FIELD)

      @Retention(RetentionPolicy.RUNTIME)

      @Documented

      @Inherited

      0x6 Java系列:Java注解詳解

      public?@interface?Column?{

      String?value();

      }

      定義一個(gè)User類,在該類的加上@Table注解,在具體的字段上@Column注解,代碼如下:

      @Table("user")

      public?class?User?{

      @Column("id")

      private?int?id;

      @Column("name")

      private?String?name;

      @Column("age")

      private?int?age;

      @Column("address")

      private?String?address;

      ..//省略getter?setter

      }

      寫一個(gè)生成sql語(yǔ)句的類,它是通過(guò)反射來(lái)獲取表名、字段名,加上判斷實(shí)體對(duì)象的字段值來(lái)生成查詢的sql?語(yǔ)句的。代碼如下:

      public?class?GenUserSql?{

      public?static?void?main(String[]?args)?throws?NoSuchMethodException,?IllegalAccessException,?InvocationTargetException?{

      User?u1?=?new?User();

      User?u2?=?new?User();

      u1.setId(1);

      u2.setName("forezp");

      genSql(u2);

      genSql(u1);

      }

      private?static?void?genSql(User?user)?throws?NoSuchMethodException,?InvocationTargetException,?IllegalAccessException?{

      Class?c?=?user.getClass();

      StringBuilder?stringBuilder?=?new?StringBuilder();

      stringBuilder.append("select?*?from?");

      if?(c.isAnnotationPresent(Table.class))?{

      Table?table?=?(Table)?c.getAnnotation(Table.class);

      String?tableName?=?table.value();

      stringBuilder.append(tableName).append("?where?1=1?and?");

      }

      Field[]?fields?=?c.getDeclaredFields();

      for?(Field?field?:?fields)?{

      String?columnName;

      if?(field.isAnnotationPresent(Column.class))?{

      Column?column?=?field.getAnnotation(Column.class);

      columnName?=?column.value();

      }?else?{

      continue;

      }

      String?fieldName?=?field.getName();

      String?getMethodName?=?"get"?+?fieldName.substring(0,?1).toUpperCase()?+?fieldName.substring(1);

      Method?method?=?c.getMethod(getMethodName);

      Object?fieldValue?=?method.invoke(user);

      if?(fieldValue?==?null?||?((fieldValue?instanceof?Integer)?&&?(Integer)?fieldValue?==?0))?{

      continue;

      }

      if?(fieldValue?instanceof?Integer)?{

      stringBuilder.append(columnName?+?"="?+?fieldValue);

      }

      if?(fieldValue?instanceof?String)?{

      stringBuilder.append(columnName?+?"="?+?"'"?+?fieldValue?+?"'");

      }

      }

      System.out.println(stringBuilder.toString());

      }

      }

      運(yùn)行程序,控制臺(tái)打印如下:

      >

      select * from user where 1=1 and name=’forezp’

      select * from user where 1=1 and id=1

      參考資料

      http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

      慕課網(wǎng)視頻

      源碼下載

      https://github.com/forezp/java-study

      方志朋簡(jiǎn)介:SpringCloud中國(guó)社區(qū)聯(lián)合創(chuàng)始人,博客訪問(wèn)量突破一千萬(wàn),愛(ài)好開(kāi)源,熱愛(ài)分享,活躍于各大社區(qū),保持著非常強(qiáng)的學(xué)習(xí)驅(qū)動(dòng)力,終身學(xué)習(xí)踐行者,終身學(xué)習(xí)受益者。目前就職于國(guó)內(nèi)某家知名互聯(lián)網(wǎng)保險(xiǎn)公司,擔(dān)任DEVOPS工程師,對(duì)微服務(wù)領(lǐng)域和持續(xù)集成領(lǐng)域研究較深,精通微服務(wù)框架SpringCloud

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:REPLACE(replace drum什么意思)
      下一篇:excel意思(excel意思是)
      相關(guān)文章
      亚洲图片中文字幕| 亚洲精品国产精品乱码不99| 亚洲avav天堂av在线不卡| 亚洲一级片免费看| 亚洲日韩涩涩成人午夜私人影院| 亚洲欧美日韩一区二区三区 | 亚洲高清偷拍一区二区三区| 亚洲av无码一区二区三区人妖| 亚洲一区精彩视频| 亚洲国产成人精品激情| 亚洲人成毛片线播放| 亚洲日产2021三区在线| 亚洲性色高清完整版在线观看| 亚洲沟沟美女亚洲沟沟| 亚洲性色高清完整版在线观看| 亚洲人成在线免费观看| 亚洲最大在线观看| 亚洲国产精品无码久久久| 亚洲国产综合自在线另类| 亚洲午夜精品一区二区公牛电影院 | 国产AV无码专区亚洲AV男同| 亚洲精品高清无码视频| 国产l精品国产亚洲区在线观看| 久久香蕉国产线看观看亚洲片| 亚洲AV区无码字幕中文色| 亚洲嫩草影院久久精品| 亚洲色图视频在线观看| 亚洲国产av一区二区三区丶| 精品国产日韩久久亚洲| 亚洲av无码一区二区三区在线播放 | WWW亚洲色大成网络.COM| 午夜亚洲福利在线老司机| 亚洲性久久久影院| 亚洲精品乱码久久久久久中文字幕| 亚洲av中文无码乱人伦在线r▽| 亚洲AV一宅男色影视| 亚洲成AV人片久久| 亚洲一本到无码av中文字幕| 久久精品国产亚洲AV未满十八| 亚洲第一黄色网址| 精品亚洲综合久久中文字幕|