摘要:元注解元注解用于注解其他注解的。該注解表明子類是有繼承了父類的注解。在注解中,需要使用四種元注解來聲明注解的作用范圍生命周期繼承,是否生成文檔等。另外在注解中也可以有自己的成員變量,如果一個注解沒有成員變量則稱為標記注解。
在使用SpringBoot作為Web敏捷開發的框架之后,SpringBoot除了自動裝配配置的便捷之外,在很多時候需要基于注解來開發。注解不僅增加了代碼的可讀性,還增加了開發的速度。這篇文章主要講述Java 注解。
元注解
元注解用于注解其他注解的。Java 5.0定義了4個標準的元注解,如下:
@Target @Retention @Documented Inherited
現在來說說這四個元注解有什么作用
@Target
@Target注解用于聲明注解的作用范圍,例如作用范圍為類、接口、方法等。它的取值以及值所對應的范圍如下:
**CONSTRUCTOR:用于描述構造器
FIELD:用于描述域
LOCAL_VARIABLE:用于描述局部變量
METHOD:用于描述方法
PACKAGE:用于描述包
PARAMETER:用于描述參數
TYPE:用于描述類、接口(包括注解類型) 或enum聲明**
@Retention
該注解聲明了注解的生命周期,即注解在什么范圍內有效。
*SOURCE:在源文件中有效
CLASS:在class文件中有效
RUNTIME:在運行時有效(即運行時保留)
大多數注解都為RUNTIME*
@Documented
是一個標記注解,有該注解的注解會在生成 java 文檔中保留。
@Inherited
該注解表明子類是有繼承了父類的注解。比如一個注解被該元注解修飾,并且該注解的作用在父類上,那么子類有持有該注解。如果注解沒有被該元注解修飾,則子類不持有父類的注解。
自定義注解
在Java開發者,JDK自帶了一些注解,在第三方框架Spring 帶了大量的注解,這些注解稱為第三方注解。在很多實際開發過程中,我們需要定義自己的注解。那么現在以案例的方式來講解自定義注解。
在注解中,需要使用四種元注解來聲明注解的作用范圍、生命周期、繼承,是否生成文檔等。另外在注解中也可以有自己的成員變量,如果一個注解沒有成員變量則稱為標記注解。注解的成員變量,只支持原始類型、Class、Enumeration、Annoation。
現在定義一個@Writer注解,該注解被Retention、Documented、Inherited、Target修飾,表明該注解的作用范圍為類、接口和方法,生命周期為運行時、該注解生成文檔,并且子類可繼承該注解。該注解有2個成員變量,一個為name一個為 age,代碼如下:
@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Target({ElementType.TYPE,ElementType.METHOD}) public @interface Writer { String name(); int age(); }
那么有了該注解,怎么用呢?
該注解的作用范圍為類、方法,寫一個WriterTest,代碼如下:
@Writer(name = "forezp", age = 12) public class WriterTest { @Writer(name = "miya", age = 10) public void writeBlog() { System.out.println("writing blog"); } }
該類有了這個注解有何用?
一般來說,用該類修飾的類,需要通過反射來做一下邏輯的開發的工作,可廣泛用于AOP、程序的配置等。現在寫一個方法通過反射來解析該注解:
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()); } } }
這些代碼基本為反射的內容,因為反射在另一篇文章已經詳細講述過,不再重復,運行該Main方法,控制臺打印出如下內容:
*name:forezp age:12
name:miya age:10*
案例實戰
有了上述的講解,你可能對注解有所了解,但是對注解的具體應用并不是很深刻。現在以一個案例來詳細講述。
大家都對ORM框架Mybitis都非常的熟悉,在這個框架中用了大量的注解。現在模仿這個框架,通過自定義注解,來解析sql 的查詢語句。實現過程大概如下:
*定義@Table @Colum注解
定義一個實體User,定義一些基本的字段,并用注解修飾
用User類new對象,給對象的某些字段賦值
通過反射和注解來生成sql 的查詢語句*
首先定義個一個Table注解,它的作用范圍為類,代碼如下:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Inherited public @interface Table { String value() default ""; }
定義一個Column注解,作用范圍為字段,代碼如下:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Column { String value(); }
定義一個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 }
寫一個生成sql語句的類,它是通過反射來獲取表名、字段名,加上判斷實體對象的字段值來生成 查詢的 sql 語句的。代碼如下:
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()); } }
運行程序,控制臺打印如下:
*>
select * from user where 1=1 and name="forezp"
select from user where 1=1 and id=1
歡迎加入學習交流群569772982,大家一起學習交流。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70499.html
摘要:注解概念注解也被成為元數據為我們在代碼中添加信息提供了一種形式化的方式,使我們可以在稍后的某個時刻更容易的使用這些數據。 注解 概念 注解(也被成為元數據)為我們在代碼中添加信息提供了一種形式化的方式,使我們可以在稍后的某個時刻更容易的使用這些數據。 注解是 Java 5 所引入的眾多語言變化之一: 注解使得我們可以以編譯器驗證的格式存儲程序的額外信息 注解可以生成描述符文件,甚至是...
摘要:核心注解講解最大的特點是無需配置文件,能自動掃描包路徑裝載并注入對象,并能做到根據下的包自動配置。所以最核心的個注解就是這是添加的一個注解,用來代替配置文件,所有這個配置文件里面能做到的事情都可以通過這個注解所在類來進行注冊。 最近面試一些 Java 開發者,他們其中有些在公司實際用過 Spring Boot, 有些是自己興趣愛好在業余自己學習過。然而,當我問他們 Spring Boo...
摘要:使用會涉及到各種各樣的配置,如開發測試線上就至少套配置信息了。本章內容基于進行詳解。添加測試類運行單元測試,程序輸出根據以上參數動態調整,發現參數會被正確被覆蓋。了解了各種配置的加載順序,如果配置被覆蓋了我們就知道是什么問題了。 使用 Spring Boot 會涉及到各種各樣的配置,如開發、測試、線上就至少 3 套配置信息了。Spring Boot 可以輕松的幫助我們使用相同的代碼就能...
摘要:從使用到原理學習線程池關于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現在軟件開發中,分散于應用中多出的功能被稱為橫切關注點如事務安全緩存等。 Java 程序媛手把手教你設計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
閱讀 1898·2021-11-24 09:39
閱讀 2134·2021-09-22 15:50
閱讀 1991·2021-09-22 14:57
閱讀 699·2021-07-28 00:13
閱讀 1065·2019-08-30 15:54
閱讀 2356·2019-08-30 15:52
閱讀 2686·2019-08-30 13:07
閱讀 3787·2019-08-30 11:27