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集成关键点
- 组件扫描:
- 确保注解定义类在@SpringBootApplication扫描路径下
- AOP处理类需添加@Component注解
- AOP代理配置:
- # application.properties
- spring.aop.auto=true # 启用AOP自动代理
- spring.aop.proxy-target-class=true # 使用CGLIB代理
复制代码 - 注解属性设计原则:
- 优先使用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)最佳实践建议:
- 优先使用注解+AOP实现通用功能
- 反射用于无法通过注解实现的动态场景
- 高频操作务必进行性能优化
- 合理设计注解属性,保持简洁性
掌握反射和自定义注解,将使你能够深入理解Java生态框架的工作原理,并能够设计和实现更加灵活、可扩展的系统架构。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |