文章目录
- 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 {@Overridepublic void sayHello() {System.out.println("Hello from Person!");}@Overridepublic 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;}@Overridepublic 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(面向切面编程)。