自定義註解+反射 實現給註解新增功能的效果
註解我們經常會用到,或者在jdk原始碼中也會看到,例如: @Deprecated
以及我們在spring或者springboot中經常用到@Controller、@Service、@Repository、@Entity
等註解。
是否思考過他們是怎麼工作的?
下面我們使用 自定義註解 + 反射
給註解加上功能
先貼出整體效果圖:
原始碼:java8環境
一、定義註解
jdk提供了自定義註解的工具類,在 java.lang.annotation
包下
先看下自定義註解的模板:(模板後面有解釋)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 註解
@Target({ElementType.FIELD,ElementType.METHOD}) // 定義 @MyAnnotation註解能加在哪些地方,這裡表示可以加在欄位和方法上
public @interface MyAnnotation {
String value() default "";
}
第一個注意點是介面需要加上@
,也就是@interface
@Retention 可以用來修飾註解,是註解的註解,稱為元註解。有下面三種值
1、RetentionPolicy.SOURCE:註解只保留在原始檔,當Java檔案編譯成class檔案的時候,註解被遺棄;
2、RetentionPolicy.CLASS:註解被保留到class檔案,但jvm載入class檔案時候被遺棄,這是預設的生命週期;
3、RetentionPolicy.RUNTIME
:註解不僅被儲存到class檔案中,jvm載入class檔案之後,仍然存在;最常用
@Target 表示當前註解可以註解在哪些內容上
ElementType列舉值 | 註解作用的範圍 |
---|---|
FIELD | 欄位上 |
METHOD | 方法上 |
PARAMETER | 方法的引數上 |
CONSTRUCTOR | 構造方法上 |
PACKAGE | 包上,參考部落格 |
MODULE | 模組上 jdk9新增 |
TYPE | 類、介面(包括註解型別)、列舉宣告、使用者自定義的註解 |
TYPE_USE | 任意使用型別的地方 |
TYPE_PARAMETER | 任何宣告型別的地方 |
LOCAL_VARIABLE | 本地變數上 |
ANNOTATION_TYPE | 元註解上 |
RECORD_COMPONENT | record類上jdk14新值 |
二、實體類上使用註解
加上註解的User物件,暫時註解和物件沒有任何關係,只是加上了註解,不要妄想這樣註解就能用了,功能部分都要我們自己新增進去,不然鬼知道這個註解到底有什麼用途。
如果你想讓註解注入屬性值、判空等操作,那麼我們需要通過反射來處理,後面有使用反射給加上註解的欄位賦值
public class User {
@MyAnnotation(value = "z3")
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
三、給註解新增功能
通過反射獲取欄位上的註解,然後獲得註解上的值,將註解中的值注入對應欄位中
如果要做其它操作,例如判空,賦初值。則得到欄位後自己根據需求修改即可。下面只是一個測試案例。
import java.lang.reflect.Field;
import java.util.Optional;
public class MyAnnotationTest {
public static void main(String[] args) {
User user = new User(); // 得到一個一個物件
Field[] fields = user.getClass().getDeclaredFields();// 反射方式得到物件的所有欄位
for (int i = 0; i < fields.length; i++) { // 遍歷欄位陣列
fields[i].setAccessible(true); // 將當前欄位設定為可訪問,不然後面就會報錯
MyAnnotation annotation = fields[i].getAnnotation(MyAnnotation.class); // 獲得這個欄位的註解
Optional<MyAnnotation> annotationOptional = Optional.ofNullable(annotation);// 通過java8的Optional容器包裹
if (!annotationOptional.isEmpty()) { // 判斷註解是否存在,age屬性沒有新增註解因此需要判空
String value = annotation.value(); // 得到註解上的值,如果沒有值則會是預設的 "" 註解的value方法的default設定
try {
fields[i].set(user, value); // 給欄位賦值
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
fields[i].setAccessible(false); // 重新將欄位設定為不可訪問
}
System.out.println(user.toString()); // 列印賦值後的user物件
}
}
相關文章
- JAVA-註解(2)-自定義註解及反射註解Java反射
- 自定義註解以及註解在反射中的應用反射
- Java中的註解-自定義註解Java
- 筆記3:自定義註解的實現筆記
- 自定義註解
- SpringBoot中搭配AOP實現自定義註解Spring Boot
- 自定義JAVA註解Java
- 自定義ConditionalOnXX註解
- 安卓自定義註解支援和示例實現安卓
- Feign通過自定義註解實現路徑的轉義
- springBoot自定義註解的使用Spring Boot
- 註解 & 反射反射
- Java註解-後設資料、註解分類、內建註解和自定義註解Java
- Spring 實現策略模式--自定義註解方式解耦if...elseSpring模式解耦
- 使用自定義註解透過BeanPostProcessor實現策略模式Bean模式
- Springboot AOP 自定義註解實現系統日誌Spring Boot
- 自定義註解例項實現SQL語句生成SQL
- 註解和反射反射
- 註解與反射反射
- Java反射-註解Java反射
- java中如何自定義註解Java
- Spring Boot 自定義註解失效Spring Boot
- SpringBoot自定義校驗註解Spring Boot
- 自定義校驗註解ConstraintValidatorAI
- 工作常備:自定義註解實現資料脫敏
- Aop+自定義註解實現資料字典翻譯
- Java高階特性-註解:註解實現Excel匯出功能JavaExcel
- java自定義註解學習(三)_註解解析及應用Java
- 聊聊如何通過自定義註解實現springmvc和sentinel整合SpringMVC
- Java註解和反射Java反射
- Java 註解和反射Java反射
- Java反射與註解Java反射
- IDEA自定義類註釋和方法註釋(自定義groovyScript方法實現多行引數註釋)Idea
- 自定義註解|切面|反射|策略模式進行入參比較校驗反射模式
- 總結一下公共欄位(aop加自定義註解加反射)反射
- Java ”框架 = 註解 + 反射 + 設計模式“ 之 註解詳解Java框架反射設計模式
- Flutter利用註解生成可自定義的路由Flutter路由
- 你的開發利器Spring自定義註解Spring