开发者

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)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜