Java反射與自定義注解實(shí)戰(zhàn)指南詳解
第一部分:Java反射核心機(jī)制
一、反射的本質(zhì)與價(jià)值
反射是Java在運(yùn)行時(shí)動(dòng)態(tài)獲取類信息并操作類的能力,它是框架設(shè)計(jì)的基石。通過(guò)反射,我們可以在運(yùn)行時(shí):
- 獲取類的完整結(jié)構(gòu)(類名、方法、屬性等)
- 動(dòng)態(tài)創(chuàng)建對(duì)象
- 調(diào)用方法和訪問(wèn)字段(包括私有成員)
- 實(shí)現(xiàn)動(dòng)態(tài)代理
二、反射核心類
| 類名 | 用途 |
|---|---|
Class | 類的元數(shù)據(jù)入口 |
Field | 類的成員變量 |
Method | 類的方法 |
Constructor | 類的構(gòu)造方法 |
三、獲取Class對(duì)象的三種方式
// 1. 類名.class(最安全高效)
Class<String> clazz1 = String.class;
// 2. 對(duì)象.getClass()
String s = "";
Class<?> clazz2 = s.getClass();
// 3. Class.forName()(最靈活)
Class<?> clazz3 = Class.forName("java.lang.String");四、反射基礎(chǔ)操作
1. 創(chuàng)建對(duì)象
// 無(wú)參構(gòu)造
Class<?> clazz = User.class;
User user = clazz.getDeclaredConstructor().newInstance();
// 有參構(gòu)造
Constructor<?> cons = clazz.getConstructor(String.class, int.class);
User user = (User) cons.newInstance("Alice", 25);2. 操作字段
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 突破私有限制
// 設(shè)置值
field.set(user, "Bob");
// 獲取值
String name = (String) field.get(user);3. 調(diào)用方法
Method method = clazz.getMethod("setName", String.class);
method.invoke(user, "Charlie"); // 調(diào)用方法五、反射應(yīng)用場(chǎng)景
- 框架設(shè)計(jì)(如Spring IOC容器)
- 動(dòng)態(tài)代理
- 注解處理器
- JSON序列化/反序列化
性能提示:反射操作比直接調(diào)用慢10-100倍,高頻場(chǎng)景建議緩存
Method/Field對(duì)象。
第二部分:自定義注解與Spring Boot實(shí)戰(zhàn)
一、自定義注解基礎(chǔ)
1. 元注解(定義注解的注解)
| 元注解 | 作用 |
|---|---|
@Target | 指定注解作用目標(biāo)(類/方法/字段) |
@Retention | 指定注解保留策略(SOURCE/CLASS/RUNTIME) |
@Documented | 是否包含在Javadoc中 |
@Inherited | 是否允許子類繼承 |
2. 定義注解
// 示例:方法耗時(shí)監(jiān)控注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeMonitor {
String taskName() default ""; // 屬性帶默認(rèn)值
int threshold() default 1000; // 超時(shí)閾值(毫秒)
}二、Spring Boot中自定義注解實(shí)戰(zhàn)
1. 使用注解
@Service
public class OrderService {
@TimeMonitor(taskName = "訂單處理", threshold = 500)
public void processOrder() {
// 業(yè)務(wù)代碼...
}
}2. 處理注解(AOP方式)
@Aspect // 聲明為切面
@Component // 納入Spring容器
public class TimeMonitorAspect {
/**
* 環(huán)繞通知:攔截帶@TimeMonitor注解的方法
*/
@Around("@annotation(monitor)")
public Object monitorTime(ProceedingJoinPoint pjp, TimeMonitor monitor) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed(); // 執(zhí)行目標(biāo)方法
long cost = System.currentTimeMillis() - start;
// 超過(guò)閾值打印警告
if (cost > monitor.threshold()) {
System.err.printf("[%s] 執(zhí)行耗時(shí) %dms (超過(guò)閾值 %dms)%n",
monitor.taskName(), cost, monitor.threshold());
}
return result;
}
}三、實(shí)際應(yīng)用場(chǎng)景
場(chǎng)景1:權(quán)限控制注解
// 定義注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
String[] roles() default {"USER"}; // 允許的角色
}
// 使用
@RestController
public class AdminController {
@Auth(roles = {"ADMIN"})
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) { ... }
}
// AOP權(quán)限校驗(yàn)
@Around("@annotation(auth)")
public Object checkAuth(ProceedingJoinPoint pjp, Auth auth) {
// 獲取當(dāng)前用戶角色
Set<String> userRoles = getCurrentUserRoles();
// 檢查權(quán)限
if (!hasRequiredRole(userRoles, auth.roles())) {
throw new AccessDeniedException("權(quán)限不足");
}
return pjp.proceed();
}場(chǎng)景2:自動(dòng)日志注解
// 定義
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoLog {
String value() default "";
}
// AOP處理
@Around("@annotation(log)")
public Object logMethod(ProceedingJoinPoint pjp, AutoLog log) throws Throwable {
String methodName = pjp.getSignature().getName();
System.out.println("【" + log.value() + "】開(kāi)始執(zhí)行: " + methodName);
Object result = pjp.proceed();
System.out.println("【" + log.value() + "】執(zhí)行完成");
return result;
}四、Spring Boot集成關(guān)鍵點(diǎn)
組件掃描:
- 確保注解定義類在
@SpringBootApplication掃描路徑下 - AOP處理類需添加
@Component注解
- 確保注解定義類在
AOP代理配置:
# application.properties spring.aop.auto=true # 啟用AOP自動(dòng)代理 spring.aop.proxy-target-class=true # 使用CGLIB代理
注解屬性設(shè)計(jì)原則:
- 優(yōu)先使用
value作為主屬性名 - 為所有屬性提供默認(rèn)值
- 復(fù)雜配置使用嵌套注解
- 優(yōu)先使用
五、反射與注解的協(xié)同工作
// 反射方式讀取注解信息
public void scanAnnotations() {
Class<?> clazz = OrderService.class;
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(TimeMonitor.class)) {
TimeMonitor monitor = method.getAnnotation(TimeMonitor.class);
System.out.println("監(jiān)控方法: " + monitor.taskName());
}
}
}總結(jié)對(duì)比
| 特性 | 反射 | 自定義注解 |
|---|---|---|
| 主要目的 | 運(yùn)行時(shí)操作類 | 為代碼添加元數(shù)據(jù) |
| 核心類 | Class, Method, Field | @interface |
| 使用場(chǎng)景 | 框架開(kāi)發(fā)、動(dòng)態(tài)代理 | AOP增強(qiáng)、配置聲明 |
| Spring Boot集成 | 直接可用 | 需配合AOP或反射處理 |
| 性能影響 | 較大(需緩存優(yōu)化) | 較?。ˋOP有代理開(kāi)銷) |
| 典型應(yīng)用 | Spring IOC容器 | Spring聲明式事務(wù)(@Transactional) |
最佳實(shí)踐建議:
- 優(yōu)先使用注解+AOP實(shí)現(xiàn)通用功能
- 反射用于無(wú)法通過(guò)注解實(shí)現(xiàn)的動(dòng)態(tài)場(chǎng)景
- 高頻操作務(wù)必進(jìn)行性能優(yōu)化
- 合理設(shè)計(jì)注解屬性,保持簡(jiǎn)潔性
掌握反射和自定義注解,將使你能夠深入理解Java生態(tài)框架的工作原理,并能夠設(shè)計(jì)和實(shí)現(xiàn)更加靈活、可擴(kuò)展的系統(tǒng)架構(gòu)。
到此這篇關(guān)于Java反射與自定義注解實(shí)戰(zhàn)指南詳解的文章就介紹到這了,更多相關(guān)Java反射與自定義注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
idea使用war以及war exploded的區(qū)別說(shuō)明
本文詳細(xì)解析了war與warexploded兩種部署方式的差異及步驟,war方式是先打包成war包,再部署到服務(wù)器上;warexploded方式是直接把文件夾、class文件等移到Tomcat上部署,支持熱部署,開(kāi)發(fā)時(shí)常用,文章分別列出了warexploded模式和war包形式的具體操作步驟2024-10-10
SpringBoot實(shí)現(xiàn)統(tǒng)一功能處理的教程詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實(shí)現(xiàn)統(tǒng)一功能處理,文中的示例代碼講解詳細(xì),對(duì)大家學(xué)習(xí)或工作有一定借鑒價(jià)值,感興趣的同學(xué)可以參考閱讀下2023-05-05
SpringBoot項(xiàng)目整合MybatisPlus并使用SQLite作為數(shù)據(jù)庫(kù)的過(guò)程
SQLite是一個(gè)緊湊的庫(kù),啟用所有功能后,庫(kù)大小可以小于 750KiB, 具體取決于目標(biāo)平臺(tái)和編譯器優(yōu)化設(shè)置, 內(nèi)存使用量和速度之間需要權(quán)衡,這篇文章主要介紹了SpringBoot項(xiàng)目整合MybatisPlus并使用SQLite作為數(shù)據(jù)庫(kù),需要的朋友可以參考下2024-07-07
淺析fastjson2時(shí)間序列化和反序列化的簡(jiǎn)單使用
在項(xiàng)目中將fastjson升級(jí)為fastjson2后,我們遇到了一些與fastjson不完全兼容的問(wèn)題,所以本文就來(lái)探討下fastjson2的時(shí)間序列化和反序列化的簡(jiǎn)單使用吧2025-01-01

