日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用自定义注解做点什么——自定义注解有什么用

發(fā)布時(shí)間:2025/3/12 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用自定义注解做点什么——自定义注解有什么用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

用自定義注解做點(diǎn)什么

前言


你不一定聽過注解,但你一定對@Override不陌生。

當(dāng)我們重寫父類方法的時(shí)候我們就看到了@Override。我們知道它表示父類方法被子類重寫了。

現(xiàn)在告訴你,@Override就是一個(gè)注解。

也許你會疑惑注解是什么?
注解(annotation)是JDK5之后引進(jìn)的新特性,是一種特殊的注釋,之所以說它特殊是因?yàn)椴煌谄胀ㄗ⑨?#xff08;comment)能存在于源碼,而且還能存在編譯期跟運(yùn)行期,會最終編譯成一個(gè).class文件,所以注解能有比普通注釋更多的功能。

接下來,先入個(gè)門,然后通過實(shí)戰(zhàn)來證明注解有多“猛”。

PS : 如果已經(jīng)了解的小伙伴可自行跳到 自定義注解實(shí)戰(zhàn)。

自定義注解入門


我們對于注解的認(rèn)識大多數(shù)來源于標(biāo)準(zhǔn)注解(也稱為內(nèi)建注解)。

標(biāo)準(zhǔn)注解表示的意義
@Override用于標(biāo)識該方法繼承自超類 當(dāng)父類的方法被刪除或修改了,編譯器會提示錯(cuò)誤信息
@Deprecated表示該類或者該方法已經(jīng)不推薦使用 如果用戶還是要使用,會生成編譯的警告
@SuppressWarnings用于忽略的編譯器警告信息

Java不僅僅提供我們原有的注解使用,它還允許我們自定義注解。比如你可以像這樣:

public @interface DoSomething {public String name() default "write"; }

這是最簡單的注解聲明。
盡管看上去像是接口的寫法,但完全不是一回事。這一點(diǎn)要注意。
而使用注解也很簡單,可以像這樣:

@DoSomething(name = "walidake")//可以顯式傳值進(jìn)來,此時(shí)name=walidake public class UseAnnotation {}@DoSomething//如果不傳值,則默認(rèn)name=我們定義的默認(rèn)值,即我們上面定義的"write" public class UseAnnotation {}

需要注意的是當(dāng)注解有value()方法時(shí),不需要指明具體名稱

public @interface DoSomething {public String value();public String name() default "write"; }@DoSomething("walidake") public class UseAnnotation {}

然而“最簡單的自定義注解”并沒有特別的意義。所以,這時(shí)候我們需要引入一個(gè)元注解的概念。

我們需要知道這些概念:
“普通注解”只能用來注解“代碼”,而**“元注解”只能用來注解 “普通注解”**。
自定義注解是“普通注解”

JDK5時(shí)支持的元注解有@Documented @Retention @Target @Inherited,接下來分別介紹它們修飾注解的效果。

@Documented @interface DocumentedAnnotation{}@interface UnDocumentedAnnotation{}@DocumentedAnnotation @UnDocumentedAnnotation public class UseDocumentedAnnotation{}

打開小黑窗,運(yùn)行javadoc UseDocumentedAnnotation.java

運(yùn)行結(jié)果:

結(jié)論:可以看到,被@Documented修飾的注解會生成到j(luò)avadoc中,如@DocumentedAnnotation。
而不被@Documented修飾的注解(@UnDocumentedAnnotation)不會生成到j(luò)avadoc中。

注解的級別
@Retention可以設(shè)置注解的級別,分為三種,都有其特定的功能。
這個(gè)元注解是我們關(guān)注的重點(diǎn),后面實(shí)戰(zhàn)我們會用到。

注解級別存在范圍主要用途
SOURCE 源碼級別注解只存在源碼中功能是與編譯器交互,用于代碼檢測。 如@Override,@SuppressWarings。 額外效率損耗發(fā)生在編譯時(shí)
CLASS 字節(jié)碼級別注解存在源碼與字節(jié)碼文件中主要用于編譯時(shí)生成額外的文件,如XML,Java文件等,但運(yùn)行時(shí)無法獲得。 這個(gè)級別需要添加JVM加載時(shí)候的代理(javaagent),使用代理來動態(tài)修改字節(jié)碼文件
RUNTIME 運(yùn)行時(shí)級別注解存在源碼,字節(jié)碼與Java虛擬機(jī)中主要用于運(yùn)行時(shí)反射獲取相關(guān)信息

限制注解使用的范圍
注解默認(rèn)可以修飾各種元素,而使用@Target可以限制注解的使用范圍。

例如,可以限定注解只能修飾方法。

@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override {}

上面的代碼將注解的使用范圍限制在了方法上,而不能用來修飾類。

試著用@Override修飾類會得到“The annotation @Override is disallowed for this location”的錯(cuò)誤。

@Target支持的范圍(參見ElementType):

1) 類,接口,注解; 2) 屬性域; 3) 方法; 4) 參數(shù); 5) 構(gòu)造函數(shù); 6) 局部變量; 7) 注解類型; 8) 包

注解的繼承
@Inherited可以讓注解類似被“繼承”一樣。
通過使用@Inherited,可以讓子類對象使用getAnnotations()獲取父類@Inherited修飾的注解。

@Inherited @Retention(RetentionPolicy.RUNTIME) @interface Inheritable{}@interface UnInheritable{}public class UseInheritedAnnotation{@UnInheritable@Inheritablepublic static class Super{}public static class Sub extends Super {}public static void main(String... args){Super instance=new Sub();//result : [@com.walidake.annotation.util.Inheritable()]System.out.println(Arrays.toString(instance.getClass().getAnnotations()));} }

我們干脆用@Documented查看類結(jié)構(gòu)。發(fā)現(xiàn):

這是不是恰恰證明了這種是偽繼承的說法,而不是真正的繼承。

自定義注解實(shí)戰(zhàn)


引言
Java Web開發(fā)中,對框架的理解和掌握是必須的。而在使用大多數(shù)框架的過程中,一般有兩種方式的配置,一種是基于xml的配置方式,一種是基于注解的方式。然而,越來越多的程序員(我)在開發(fā)過程中享受到注解帶來的簡便,并義無反顧地投身其中。

ORM框架,像Hibernate,Mybatis就提供了基于注解的配置方式。我們接下來就使用自定義注解實(shí)現(xiàn)袖珍版的Mybatis,袖珍版的Hibernate。

這很重要
說明:實(shí)戰(zhàn)的代碼會被文章末尾附上。而實(shí)際上在之前做袖珍版框架的時(shí)候并沒有想到會拿來做自定義注解的Demo。因此給出的代碼涉及了其他的一些技術(shù),例如數(shù)據(jù)庫連接池,動態(tài)代理等等,比較雜。
在這個(gè)篇幅我們只討論關(guān)于自定義注解的問題,至于其他的技術(shù)后面會開多幾篇博文闡述。(當(dāng)然這么多前輩面前不敢造次,有個(gè)討論學(xué)習(xí)的氛圍是很好的~)

那么在自定義注解框架前,我們需要花點(diǎn)時(shí)間瀏覽以下幾個(gè)和Annotation相關(guān)的方法。

方法名用法
Annotation getAnnotation(Class annotationType)獲取注解在其上的annotationType
Annotation[] getAnnotations()獲取所有注解
isAnnotationPresent(Class annotationType)判斷當(dāng)前元素是否被annotationType注解
Annotation[] getDeclareAnnotations()與getAnnotations() 類似,但是不包括父類中被Inherited修飾的注解

Mybatis 自定義注解

本節(jié)目標(biāo):自定義注解實(shí)現(xiàn)Mybatis插入數(shù)據(jù)操作。
本節(jié)要求:細(xì)心觀察使用自定義注解的步驟。

Step 1 : 聲明自定義注解。

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Insert {public String value(); }

Step 2 : 在規(guī)定的注解使用范圍內(nèi)使用我們的注解

public interface UserMapper {@Insert("insert into user (name,password) values (?,?)")public void addUser(String name,String password);}

Step 3 : 通過method.getAnnotation(Insert.class).value()使用反射解析自定義注解,得到其中的sql語句

//檢查是否被@Insert注解修飾 if (method.isAnnotationPresent(Insert.class)) {//檢查sql語句是否合法//method.getAnnotation(Insert.class).value()取得@Insert注解value中的Sql語句sql = checkSql(method.getAnnotation(Insert.class).value(),Insert.class.getSimpleName());//具體的插入數(shù)據(jù)庫操作insert(sql, parameters); }

Step 4 : 根據(jù)實(shí)際場景調(diào)用Step 3的方法

UserMapper mapper = MethodProxyFactory.getBean(UserMapper.class); mapper.addUser("walidake","665908");

運(yùn)行結(jié)果:

以上節(jié)選自annotation中Mybatis部分。具體CRUD操作請看源碼。

總結(jié)一下從上面學(xué)到的東西:
1.聲明自定義注解,并限制適用范圍(因?yàn)槟J(rèn)是通用)
2.規(guī)定范圍內(nèi)使用注解
3.isAnnotationPresent(Insert.class)檢查注解,getAnnotation(Insert.class).value()取得注解內(nèi)容
4.根據(jù)實(shí)際場景應(yīng)用

Hibernate 自定義注解

本節(jié)目標(biāo):自定義注解使實(shí)體自動建表(即生成建表SQL語句)
本節(jié)要求:動手操作,把未給全的代碼補(bǔ)齊。
本節(jié)規(guī)劃:仿照Hibernate,我們大概會需要@Table,@Column,還有id,我們這里暫且聲明為@PrimaryKey

仿照自定義Mybatis注解的步驟:

/*** 可根據(jù)需要自行定制功能*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Table {String name() default "";}@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Column {// 列名 默認(rèn)為""String name() default "";// 長度 默認(rèn)為255int length() default 255;// 是否為varchar 默認(rèn)為trueboolean varchar() default true;// 是否為空 默認(rèn)可為空boolean isNull() default true; }/*** 有需要可以拆分成更小粒度* @author walidake**/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface PrimaryKey {String name() default ""; }

完成Step 1,接下來是Step 2。

@Table public class Person {@PrimaryKeyprivate int id;@Column(isNull = false, length = 20)private String username;... }

Step 3,新建一個(gè)叫做SqlUtil的類,使用Class(實(shí)體類).isAnnotationPresent(Table.class)取到@Table注解的內(nèi)容。

而我們?nèi)绾稳〉?#64;Column和@PrimaryKey的內(nèi)容?
使用反射,我們可以很容易做到。

// 反射取得所有Field Field[] fields = clazz.getDeclaredFields(); ... ... // 獲取注解對象 column = fields[i].getAnnotation(Column.class); // 設(shè)置訪問私有變量 fields[i].setAccessible(true); // 取得@Column的內(nèi)容 columnName = "".equals(column.name()) ? fields[i].getName(): column.name();

反射的內(nèi)容后面再寫。(感覺每一篇都給自己挖了很多坑后面去填)

Step 4套入使用場景

String createSql = SqlUtil.createTable(clazz); ... connection.createStatement().execute(createSql);

運(yùn)行結(jié)果:

運(yùn)行結(jié)果正確!

自此我們完成了實(shí)戰(zhàn)模塊的內(nèi)容。當(dāng)然關(guān)于Hibernate的CRUD也可以用同樣的方法做到,更進(jìn)一步還可以把二級緩存整合進(jìn)來,實(shí)現(xiàn)自己的一個(gè)微型框架。盡管現(xiàn)有的框架已經(jīng)很成熟了,但自己實(shí)現(xiàn)一遍還是能收獲很多東西。

可以看出來,注解簡化了我們的配置。每次使用注解只需要@注解名就可以了,就跟吃春藥一樣“爽”。不過由于使用了反射,后勁太“猛”,jvm無法對代碼優(yōu)化,影響了性能。這一點(diǎn)最后也會提及。

另外提一點(diǎn),之前想格式化hibernate生成的SQL,做大量搜索后被告知“Hibernate 使用的是開源的語法解析工具 Antlr,需要進(jìn)行 SQL 語法解析,將 SQL 語句整理成語法樹”。也算一個(gè)坑吧~
不過后來找到一個(gè)除了建表SQL以外的格式化工具類,覺得還不錯(cuò)就也分享了。可以在源碼中找到。

最后說點(diǎn)什么
可以發(fā)現(xiàn)我們使用運(yùn)行時(shí)注解來搭建我們的袖珍版ORM框架,因?yàn)檫\(yùn)行時(shí)注解來搭建框架相對容易而且適用性也比較廣,搭建的框架使用起來也比較簡單。但在此基礎(chǔ)上因?yàn)樾枰玫椒瓷?#xff0c;其效率性能相對不高。因此,多數(shù)Web應(yīng)用使用運(yùn)行時(shí)注解,而像Android等對效率性能要求較高的平臺一般使用源碼級別注解來搭建。下一節(jié)我們討論怎么玩一玩源碼級注解。

總結(jié)

以上是生活随笔為你收集整理的用自定义注解做点什么——自定义注解有什么用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 天天爱夜夜爽 | 99国内揄拍国内精品人妻免费 | 色婷婷视频在线观看 | 91精品国产综合久久久密臀九色 | 99re99| 99久久99久久| 午夜性福利视频 | 日本一本高清 | 成人激情视频在线播放 | 国产一区二区久久久 | 欧美日韩少妇 | 日韩在线高清 | 爱草视频 | 国产欧美一区二区三区精华液好吗 | 欧美大片黄色 | 污漫在线观看 | 亚洲av无一区二区三区久久 | 日本免费在线视频观看 | 欧美不卡一二三 | 日本在线视频观看 | 最新一区二区三区 | 一级片免费网站 | 国产视频黄色 | 久久加久久 | 欧美男人又粗又长又大 | 久久理论| 中文一区二区 | 欧美精品一区二区三区视频 | 亚洲男人天堂2017 | 亚洲五月网 | 日韩在线精品视频 | 国产九九精品视频 | 91在线最新| 国产精品一区二区三区免费 | 欧美一级成人 | 日韩啪| 一级全黄男女免费大片 | 日本丰满少妇裸体自慰 | 精品91自产拍在线观看二区 | 中文字幕在线看片 | 日本高清视频在线播放 | 欧美性欧美zzzzzzzzz | 麻豆精品视频 | 人妻丰满熟妇av无码久久洗澡 | 高清久久久久久 | 欧美成人激情在线 | 日韩一级视频在线观看 | 色婷婷欧美 | 男人免费网站 | 中国成人毛片 | 国产精品三级电影 | 国产亚洲毛片 | 国产高清精品在线 | 中文字幕一区二区三区在线视频 | 午夜影院免费在线观看 | 婷婷五月综合缴情在线视频 | 国产精品一区二区三区久久 | 在线国产视频 | 成人美女毛片 | 97国产成人无码精品久久久 | 中文字幕无人区二 | 性视频在线 | 夜色综合| 日b视频免费观看 | 熟妇高潮一区二区 | 免费av网址大全 | www.sesehu.com| 老熟妇一区二区 | 久久免费一区 | 亚洲精品在线观看视频 | 樱桃视频一区二区三区 | 国产午夜一级 | 日韩三区在线 | 天降女子在线观看 | 伊人自拍 | 亚洲欧美一区二区在线观看 | 国产香蕉在线观看 | 操日本女人 | 色婷婷精品久久二区二区密 | 成人首页| 欧美成年视频 | 免费a大片 | 国产人妻精品午夜福利免费 | 日日插插 | 中文字幕一区二区在线观看视频 | 亚洲成人一区在线观看 | 亚洲特级毛片 | 精品国产网站 | 午夜在线小视频 | 欧美一级淫片免费视频魅影视频 | 裸体的日本在线观看 | 久久bb | 色噜噜色狠狠 | 国产经典三级在线 | 精品在线视频免费 | 久久综合亚洲精品 | 91精品综合| 欧美另类videossexo高潮 | 狂野欧美性猛交xxxxhd |