深入理解 Java 的反射、注解与动态代理
文章目录
- 一、反射:运行时的自省与操作能力
- 1.1 反射是什么?
- 1.2 基本 API 使用
- 获取类对象的三种方式:
- 获取构造器并实例化:
- 获取字段和方法:
- 二、注解:元数据的声明机制
- 2.1 注解的定义与使用
- 自定义注解:
- 使用注解:
- 解析注解:
- 三、动态代理:运行时生成接口实现
- 3.1 动态代理的应用场景
- 3.2 使用 JDK 动态代理
- 定义接口与实现:
- 创建代理处理器:
- 创建代理对象并调用:
- 四、注解 + 反射 + 代理:模拟 AOP 切面编程
- 五、总结
在 Java 的高级特性中,反射(Reflection)、注解(Annotation) 和 动态代理(Dynamic Proxy) 是构建框架、实现 AOP、ORM 等重要机制的基础。本文将逐一详解这三大特性,并辅以代码示例,帮助你在实际项目中更好地理解和运用它们。
一、反射:运行时的自省与操作能力
1.1 反射是什么?
反射是 Java 提供的一种机制,允许程序在运行时加载、探查以及操作类的结构(如方法、构造器、字段等)。
1.2 基本 API 使用
public class Person {private String name;private int age;public Person() {}public Person(String name) {this.name = name;}private void sayHello() {System.out.println("Hello, my name is " + name);}
}
获取类对象的三种方式:
Class<?> clazz1 = Person.class;
Class<?> clazz2 = new Person().getClass();
Class<?> clazz3 = Class.forName("your.package.Person");
获取构造器并实例化:
Constructor<?> constructor = clazz1.getConstructor(String.class);
Person p = (Person) constructor.newInstance("Tom");
获取字段和方法:
Field nameField = clazz1.getDeclaredField("name");
nameField.setAccessible(true); // 解除私有访问限制
nameField.set(p, "Jerry");
System.out.println(nameField.get(p)); // 输出 JerryMethod method = clazz1.getDeclaredMethod("sayHello");
method.setAccessible(true);
method.invoke(p); // 输出 Hello, my name is Jerry
二、注解:元数据的声明机制
2.1 注解的定义与使用
注解是 Java 5 引入的一种元数据机制,常用于代码标记、配置或提供信息给框架。
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecution {String value() default "执行方法";
}
使用注解:
public class UserService {@LogExecution("执行用户注册")public void register(String name) {System.out.println(name + " registered.");}
}
解析注解:
public class AnnotationProcessor {public static void main(String[] args) throws Exception {Method method = UserService.class.getMethod("register", String.class);if (method.isAnnotationPresent(LogExecution.class)) {LogExecution log = method.getAnnotation(LogExecution.class);System.out.println("日志: " + log.value());}}
}
输出:日志: 执行用户注册
三、动态代理:运行时生成接口实现
3.1 动态代理的应用场景
Java 的动态代理允许你在运行时生成一个实现了指定接口的类。常用于:
- AOP 编程(如日志、事务处理)
- RPC 框架(如 Dubbo)
- 装饰器模式的实现
3.2 使用 JDK 动态代理
定义接口与实现:
public interface HelloService {void sayHello(String name);
}public class HelloServiceImpl implements HelloService {public void sayHello(String name) {System.out.println("Hello, " + name);}
}
创建代理处理器:
public class LogInvocationHandler implements InvocationHandler {private final Object target;public LogInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("方法调用前: " + method.getName());Object result = method.invoke(target, args);System.out.println("方法调用后: " + method.getName());return result;}
}
创建代理对象并调用:
public class ProxyDemo {public static void main(String[] args) {HelloService service = new HelloServiceImpl();HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(service.getClass().getClassLoader(),service.getClass().getInterfaces(),new LogInvocationHandler(service));proxyInstance.sayHello("Alice");}
}
输出:
方法调用前: sayHello
Hello, Alice
方法调用后: sayHello
四、注解 + 反射 + 代理:模拟 AOP 切面编程
结合三者,我们可以模拟一个 AOP 实现:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {String value() default "调用方法";
}public interface UserService {@Log("用户登录")void login(String username);
}public class UserServiceImpl implements UserService {public void login(String username) {System.out.println(username + " 登录系统");}
}public class AOPHandler implements InvocationHandler {private final Object target;public AOPHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.isAnnotationPresent(Log.class)) {Log log = method.getAnnotation(Log.class);System.out.println("[AOP日志] " + log.value());}return method.invoke(target, args);}
}public class AOPDemo {public static void main(String[] args) {UserService target = new UserServiceImpl();UserService proxy = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new AOPHandler(target));proxy.login("admin");}
}
输出:
[AOP日志] 用户登录
admin 登录系统
五、总结
特性 | 用途 | 常用 API/关键词 |
---|---|---|
反射 | 运行时探查与操作类结构 | Class、Method、Field、Constructor |
注解 | 元数据标注 | @interface、@Retention、@Target |
动态代理 | 运行时增强接口逻辑、AOP 实现 | Proxy.newProxyInstance、InvocationHandler |