Java学习——day24(反射进阶:注解与动态代理)
文章目录
- 1. 反射与注解
- 2. 动态代理
- 3. 实践:编写动态代理示例
- 4. 注解定义与使用
- 5. 动态代理
- 6. 小结与思考
1. 反射与注解
- 注解:注解是 Java 提供的用于在代码中添加元数据的机制。它不会影响程序的执行,但可以在运行时通过反射获取和处理。
- 反射读取注解:
- 通过 Class、Method、Field 等反射 API 获取注解信息。
- 注解可以用于类、方法、字段等。
2. 动态代理
- 动态代理的概念:动态代理是 Java 提供的一种机制,可以在运行时创建接口的代理实例,并且可以在方法调用前后插入额外的操作。
- 使用 Proxy 类:java.lang.reflect.Proxy 类提供了创建代理对象的静态方法。
- 代理接口:通过 InvocationHandler 接口来定义代理对象的行为。
3. 实践:编写动态代理示例
- 创建一个接口,使用动态代理为其生成代理对象。
- 在代理方法中加入日志打印,打印每个方法的调用时间。
4. 注解定义与使用
注解的定义通常采用 @interface 关键字,例如:
// 定义一个自定义注解
import java.lang.annotation.*;
@Target(ElementType.METHOD) // 这个注解应用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时可以反射获取
public @interface Log {
String value() default "日志记录";
}
如何通过反射读取注解:
假设有如下类及方法上使用了注解:
import java.lang.annotation.*;
public class Example {
// 应用自定义注解
@Log(value = "执行sayHello方法")
public void sayHello() {
System.out.println("Hello, World!");
}
public static void main(String[] args) {
try {
// 获取 sayHello 方法的 Class 对象
Method method = Example.class.getMethod("sayHello");
// 判断该方法是否有 Log 注解
if (method.isAnnotationPresent(Log.class)) {
// 获取注解的值
Log log = method.getAnnotation(Log.class);
System.out.println("注解内容: " + log.value());
}
// 调用方法
method.invoke(new Example());
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果:
注解内容: 执行sayHello方法
Hello, World!
解释:
- @Log 注解定义了一个 value 属性,在 sayHello() 方法上使用。
- 通过反射获取方法 sayHello,使用 isAnnotationPresent 判断是否应用了注解,然后获取注解并打印 value 属性。
5. 动态代理
动态代理的原理
- 动态代理是一种在运行时创建代理对象的技术。通过 java.lang.reflect.Proxy 类和 InvocationHandler 接口,Java 实现了动态代理机制。
- 通过动态代理可以增强原对象的功能,比如记录日志、权限控制等。
创建动态代理的基本步骤
1.定义接口:代理类需要实现接口。
2.实现 InvocationHandler:InvocationHandler 用于处理代理对象的方法调用。
3.使用 Proxy.newProxyInstance():创建代理对象。
示例:为某个接口创建代理对象,并在方法调用前后打印日志
1. 定义接口
public interface Person {
void sayHello();
void work();
}
2. 实现接口
public class PersonImpl implements Person {
@Override
public void sayHello() {
System.out.println("Hello from Person!");
}
@Override
public void work() {
System.out.println("Person is working.");
}
}
3. 创建 InvocationHandler 实现类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LoggingHandler implements InvocationHandler {
private Object target;
public LoggingHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在方法执行前打印日志
System.out.println("Method " + method.getName() + " is about to be called.");
// 执行目标方法
Object result = method.invoke(target, args);
// 在方法执行后打印日志
System.out.println("Method " + method.getName() + " was called.");
return result;
}
}
4. 使用 Proxy 创建代理对象
import java.lang.reflect.Proxy;
public class DynamicProxyExample {
public static void main(String[] args) {
Person person = new PersonImpl(); // 创建目标对象
// 创建代理对象
Person proxyPerson = (Person) Proxy.newProxyInstance(
Person.class.getClassLoader(),
new Class<?>[]{Person.class},
new LoggingHandler(person)
);
// 使用代理对象调用方法
proxyPerson.sayHello();
proxyPerson.work();
}
}
输出结果:
Method sayHello is about to be called.
Hello from Person!
Method sayHello was called.
Method work is about to be called.
Person is working.
Method work was called.
解释:
- 通过 Proxy.newProxyInstance() 创建了一个 Person 接口的代理对象。代理对象会调用 LoggingHandler 的 invoke 方法。
- LoggingHandler 通过 method.invoke(target, args) 调用实际的目标方法,并在方法调用前后打印日志。
6. 小结与思考
1.反射与注解:
- 注解是一个非常强大的元数据机制,可以在运行时动态地获取类和方法的相关信息。常见应用包括框架开发、AOP(面向切面编程)等。
2.动态代理: - 动态代理是面向切面编程中的一个核心技术,它允许我们在运行时动态地为接口生成代理,并对方法执行前后进行增强(如日志、权限控制等)。
- 动态代理广泛应用于 Java 框架,如 Spring 的 AOP(面向切面编程)。