Java反射与自定义注解实战指南详解
目录
- 第一部分:Java反射核心机制
- 一、反射的本质与价值
- 二、反射核心类
- 三、获取Class对象的三种方式
- 四、反射基础操作
- 1. 创建对象
- 2. 操作字段
- 3. 调用方法
- 五编程客栈、反射应用场景
- 第二部分:自定义注解与Spring Boot实战
- 一、自定义注解基础
- 1. 元注解(定义注解的注解)
- 2. 定义注解
- 二、Spring Boot中自定义注解实战
- 1. 使用注解
- 2. 处理注解(AOP方式)
- 三、实际应用场景
- 场景1:权限控制注解
- 场景2:自动日志注解
- 四、Spring Boot集成关键点
- 五、反射与注解的协同工作
- 总结对比
第一部分: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.getConstructoEELOrOsr(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 vwww.devze.comoid 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 =js {"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集成关键点
组件扫描:
- 确保注解定义类在
@SpringBootApplication
扫描路径下 - AOP处理类需添加
@Component
注解
- 确保注解定义类在
AOP代理配置:
# application.properties spring.aop.auto=true # 启用AOP自动代理 spring.aop.proxy-target-class=true # 使用CGLIB代理
注解属性设计原则:
- 优先使用
value
作为主属性python名 - 为所有属性提供默认值
- 复杂配置使用嵌套注解
- 优先使用
五、反射与注解的协同工作
// 反射方式读取注解信息 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) |
最佳实践建议:
- 优先使用注解+AOP实现通用功能
- 反射用于无法通过注解实现的动态场景
- 高频操作务必进行性能优化
- 合理设计注解属性,保持简洁性
掌握反射和自定义注解,将使你能够深入理解Java生态框架的工作原理,并能够设计和实现更加灵活、可扩展的系统架构。
到此这篇关于Java反射与自定义注解实战指南详解的文章就介绍到这了,更多相关Java反射与自定义注解内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论