Java反射与自定义注解实战指南

第一部分:Java反射核心机制

一、反射的本质与价值

反射是Java在运行时动态获取类信息并操作类的能力,它是框架设计的基石。通过反射,我们可以在运行时:

  • 获取类的完整结构(类名、方法、属性等)
  • 动态创建对象
  • 调用方法和访问字段(包括私有成员)
  • 实现动态代理

二、反射核心类

类名 用途
Class 类的元数据入口
Field 类的成员变量
Method 类的方法
Constructor 类的构造方法

三、获取Class对象的三种方式

// 1. 类名.class(最安全高效)
Class<String> clazz1 = String.class; // 2. 对象.getClass()
String s = "";
Class<?> clazz2 = s.getClass(); // 3. Class.forName()(最灵活)
Class<?> clazz3 = Class.forName("java.lang.String");

四、反射基础操作

1. 创建对象

// 无参构造
Class<?> clazz = User.class;
User user = clazz.getDeclaredConstructor().newInstance(); // 有参构造
Constructor<?> cons = clazz.getConstructor(String.class, int.class);
User user = (User) cons.newInstance("Alice", 25);

2. 操作字段

Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 突破私有限制 // 设置值
field.set(user, "Bob"); // 获取值
String name = (String) field.get(user);

3. 调用方法

Method method = clazz.getMethod("setName", String.class);
method.invoke(user, "Charlie"); // 调用方法

五、反射应用场景

  • 框架设计(如Spring IOC容器)
  • 动态代理
  • 注解处理器
  • JSON序列化/反序列化

性能提示:反射操作比直接调用慢10-100倍,高频场景建议缓存Method/Field对象。


第二部分:自定义注解与Spring Boot实战

一、自定义注解基础

1. 元注解(定义注解的注解)

元注解 作用
@Target 指定注解作用目标(类/方法/字段)
@Retention 指定注解保留策略(SOURCE/CLASS/RUNTIME
@Documented 是否包含在Javadoc中
@Inherited 是否允许子类继承

2. 定义注解

// 示例:方法耗时监控注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeMonitor {
String taskName() default ""; // 属性带默认值
int threshold() default 1000; // 超时阈值(毫秒)
}

二、Spring Boot中自定义注解实战

1. 使用注解

@Service
public class OrderService { @TimeMonitor(taskName = "订单处理", threshold = 500)
public void processOrder() {
// 业务代码...
}
}

2. 处理注解(AOP方式)

@Aspect // 声明为切面
@Component // 纳入Spring容器
public class TimeMonitorAspect { /**
* 环绕通知:拦截带@TimeMonitor注解的方法
*/
@Around("@annotation(monitor)")
public Object monitorTime(ProceedingJoinPoint pjp, TimeMonitor monitor) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed(); // 执行目标方法
long cost = System.currentTimeMillis() - start; // 超过阈值打印警告
if (cost > monitor.threshold()) {
System.err.printf("[%s] 执行耗时 %dms (超过阈值 %dms)%n",
monitor.taskName(), cost, monitor.threshold());
}
return result;
}
}

三、实际应用场景

场景1:权限控制注解

// 定义注解
@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权限校验
@Around("@annotation(auth)")
public Object checkAuth(ProceedingJoinPoint pjp, Auth auth) {
// 获取当前用户角色
Set<String> userRoles = getCurrentUserRoles(); // 检查权限
if (!hasRequiredRole(userRoles, auth.roles())) {
throw new AccessDeniedException("权限不足");
}
return pjp.proceed();
}

场景2:自动日志注解

// 定义
@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() + "】开始执行: " + methodName);
Object result = pjp.proceed();
System.out.println("【" + log.value() + "】执行完成");
return result;
}

四、Spring Boot集成关键点

  1. 组件扫描

    • 确保注解定义类在@SpringBootApplication扫描路径下
    • AOP处理类需添加@Component注解
  2. AOP代理配置

    # application.properties
    spring.aop.auto=true # 启用AOP自动代理
    spring.aop.proxy-target-class=true # 使用CGLIB代理
  3. 注解属性设计原则

    • 优先使用value作为主属性名
    • 为所有属性提供默认值
    • 复杂配置使用嵌套注解

五、反射与注解的协同工作

// 反射方式读取注解信息
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("监控方法: " + monitor.taskName());
}
}
}

总结对比

特性 反射 自定义注解
主要目的 运行时操作类 为代码添加元数据
核心类 Class, Method, Field @interface
使用场景 框架开发、动态代理 AOP增强、配置声明
Spring Boot集成 直接可用 需配合AOP或反射处理
性能影响 较大(需缓存优化) 较小(AOP有代理开销)
典型应用 Spring IOC容器 Spring声明式事务(@Transactional)

最佳实践建议

  1. 优先使用注解+AOP实现通用功能
  2. 反射用于无法通过注解实现的动态场景
  3. 高频操作务必进行性能优化
  4. 合理设计注解属性,保持简洁性

掌握反射和自定义注解,将使你能够深入理解Java生态框架的工作原理,并能够设计和实现更加灵活、可扩展的系统架构。

Java反射与自定义注解实战指南的更多相关文章

  1. Java反射与自定义注解

    反射,在Java常用框架中屡见不鲜.它存在于java.lang.reflact包中,就我的认识,它可以拿到类的字段和方法,及构造方法,还可以生成对象实例等.对深入的机制我暂时还不了解,本篇文章着重在使 ...

  2. 利用反射跟自定义注解拼接实体对象的查询SQL

    前言 项目中虽然有ORM映射框架来帮我们拼写SQL,简化开发过程,降低开发难度.但难免会出现需要自己拼写SQL的情况,这里分享一个利用反射跟自定义注解拼接实体对象的查询SQL的方法. 代码 自定义注解 ...

  3. Android面试基础(一)IOC(DI)框架(ViewUtils)讲解_反射和自定义注解类

    1. Android中的IOC(DI)框架 1.1 ViewUtils简介(xUtils中的四大部分之一) IOC: Inverse of Controller 控制反转. DI: Dependenc ...

  4. 分享知识-快乐自己:全面解析 java注解实战指南

    请你在看这篇文章时,不要感到枯燥,从头到尾一行行看,代码一行行读,你一定会有所收获的. 问: 为什么学习注解? 学习注解有什么好处? 学完能做什么? 答: 1):能够读懂别人的代码,特别是框架相关的代 ...

  5. java 利用反射完成自定义注解

    元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明.Java5.0定义的元注解: 1.@ ...

  6. Java反射reflection与注解annotation的应用(自动测试机)

    一.关于自动测试机 1.什么是自动测试机? 对类中的指定方法进行批量测试的工具 2.自动测试机有什么用? a.避免了冗长的测试代码 当类中的成员方法很多时,对应的测试代码可能会很长,使用测试能够让测试 ...

  7. Java中的自定义注解

    ## 元注解 要声明一个注解, 我们需要元注解, 元注解是指注解的注解,包括@Retention, @Target, @Document, @Inherited. @Retention 注解的保留位置 ...

  8. Java:深入自定义注解(Annotation)

    在网上找了很多资料也有写的比较好的,但是总有有一点半点的细节没有写出来,在这里自己总结下使用. 使用Java的自定义注解,首先个人需要了解下Java为我们提供的元注解和相关定义注解的语法.(这个我在网 ...

  9. Java反射机制、注解及JPA实现

    1.java反射概述 JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称 ...

  10. java基础复习-自定义注解4(结合JDBC技术,打造类表映射微框架)

    写在前面: 1.该框架为自己所写的第一个框架类产品,可能有着许多不足的地方,读者可以到评论区指出.同时,该微框架的源码也会开源至博客中,够后来的学习者借鉴.由于该框架逻辑结构稍些复杂,不可能花大量篇幅 ...

随机推荐

  1. 一文速通Python并行计算:04 Python多线程编程-多线程同步(上)—基于条件变量、事件和屏障

    一文速通 Python 并行计算:04 Python 多线程编程-多线程同步(下)-基于条件变量.事件和屏障 摘要: 本文介绍了 Python 多线程同步的三种机制:条件变量(Condition).事 ...

  2. nginx集群同步方案

    之前公司同事写过rsync加触发nginx reload脚本,适合nginx配置内容完全一致的情况. 今天写一个同步指定文件的脚本,修改完主服务器.使用scp传输到其他nginx服务器上重启NGINX ...

  3. OpenEuler RISC-V 上跑bitcoin(实战版)

      不久前刚在OpenEuler 24.09 RISC-V上部署了 bitcoin,不过还没跑起来,这次我打算在这个环境下面运行一些应用服务,体验一下 OERV 的开发感觉.   编译出来的 bitc ...

  4. .net core-利用OpenObserve 实现OpenTelemetry可观测性标准(Logs,Traces,Metrics)

    1. 什么是 OpenObserve? OpenObserve 是一个开源的可观测性平台(支持日志.指标.追踪),旨在成为 Elasticsearch/Datadog 的轻量级替代方案. 它支持通过 ...

  5. apisix~ApisixPluginConfig的使用

    1. ApisixPluginConfig 的作用 插件配置复用:将插件配置定义为独立的资源,供多个路由或服务引用. 解耦插件与路由:修改插件配置时,只需更新 ApisixPluginConfig,无 ...

  6. fiddler抓包配置

    一.fiddler配置 打开tools-options 1.设置general,勾选对应选项 2.设置HTTPS,勾选Decrypt HTTPS traffic时,首次使用如果没有下载过fiddler ...

  7. RabbitMQ队列和消息的优先级

    RabbitMQ队列和消息的优先级 如果队列中的消息很多,需要一部分消息被优先消费,这是可以通过为消息和队列设置优先级来实现. 请注意,消息的优先级是相对于队列的优先级而言的.如果队列的最大优先级是1 ...

  8. 如何在 AI 小助手对话中显示原文预览

    写在前面 本文使用的开源工具平台包含以下内容: AI 助手平台:MaxKB 运维管理面板:1Panel Linux运维管理面板 一.整理原文链接 如果现有的文档已经有能够下载的链接或者预览链接,可以跳 ...

  9. 实战案例分享:如何基于Apache SeaTunnel全方位进行高效二次开发

    大家好,我是范佳,是Apache SeaTunnel社区的PMC member,同时也是白鲸开源高级开发工程师.今天给大家分享一些基于Apache SeaTunnel二次开发的内容. 这部分内容主要涉 ...

  10. An internal error occurred during: "Polling news feeds". javax/xml/bind/JAXBContext

    WindowPerferences取消Enable automatic news polling的勾选