网站首页 > 技术文章 正文
在 Java 中,代理有以下几种实现方式:
静态代理
- 定义与实现方式
静态代理是由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class 文件就已经存在了。静态代理通常需要实现与目标对象相同的接口,并在代理类中持有目标对象的引用。在代理方法中,可以在调用目标对象的方法前后添加额外的逻辑。例如,有一个接口Subject和一个实现了该接口的目标类RealSubject,可以创建一个代理类StaticProxy实现Subject接口,并在其中持有RealSubject的引用。
- 特点
优点:可以在不修改目标对象的情况下,为目标对象添加额外的功能。实现简单,容易理解。
缺点:如果目标对象的接口发生变化,代理类也需要相应地修改。如果有多个目标对象,需要为每个目标对象创建一个代理类,代码冗余度高。
动态代理
- Java 动态代理(基于接口)
实现原理:Java 动态代理是在运行时动态生成代理类的字节码,并加载到 JVM 中。它要求目标对象必须实现一个接口,通过java.lang.reflect.Proxy类来创建代理对象。动态代理的核心是利用反射机制,在运行时生成一个实现了目标对象接口的代理类。这个代理类包含了一个InvocationHandler接口的实现,用于处理对目标对象方法的调用。当调用代理对象的方法时,实际上会调用InvocationHandler的invoke方法。在invoke方法中,可以在调用目标对象的方法前后添加额外的逻辑,如日志记录、性能监控等。
实现步骤:
定义一个接口,目标对象和代理对象都要实现这个接口。
创建目标对象的实现类。实现InvocationHandler接口,在invoke方法中添加代理逻辑,并调用目标对象的方法。
使用Proxy.newProxyInstance方法创建代理对象,传入目标对象的类加载器、目标对象实现的接口数组和InvocationHandler实例。
Java 代码实现示例:
interface Subject {
// 定义一个方法
void doSomething();
}
class RealSubject implements Subject {
@Override
// 目标对象的方法实现
public void doSomething() {
System.out.println("RealSubject is doing something.");
}
}
class DynamicProxyHandler implements InvocationHandler {
private Object target;
public DynamicProxyHandler(Object target) {
// 传入目标对象进行保存
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before calling method.");
// 调用目标对象的方法
Object result = method.invoke(target, args);
System.out.println("After calling method.");
return result;
}
}
public class JavaDynamicProxyExample {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
// 使用动态代理创建代理对象
Subject proxySubject = (Subject) Proxy.newProxyInstance(
RealSubject.class.getClassLoader(),
new Class[]{Subject.class},
new DynamicProxyHandler(realSubject));
proxySubject.doSomething();
}
}
- CGLIB 动态代理(基于继承)
实现原理:CGLIB(Code Generation Library)是一个强大的代码生成库,可以在运行时动态生成目标类的子类作为代理类。它不需要目标类实现接口,通过继承目标类来实现代理。CGLIB 使用字节码生成技术,在运行时生成一个继承自目标类的子类,并在子类中重写目标类的方法。在重写的方法中,可以添加额外的逻辑。CGLIB 使用net.sf.cglib.proxy.Enhancer类来创建代理对象。在设置回调对象时,可以定义代理对象的方法调用行为。这个回调对象通常是一个实现了net.sf.cglib.proxy.MethodInterceptor接口的类,在intercept方法中可以处理对目标方法的调用。
实现步骤:
创建目标对象的类。
实现MethodInterceptor接口,在intercept方法中添加代理逻辑,并调用目标对象的方法。
使用Enhancer类创建代理对象,设置目标对象的类、回调对象等参数。
Java 代码实现示例:
class TargetClass {
public void doSomething() {
System.out.println("TargetClass is doing something.");
}
}
class CglibProxyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before calling method.");
// 调用目标对象的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("After calling method.");
return result;
}
}
public class CglibDynamicProxyExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetClass.class);
// 设置回调对象
enhancer.setCallback(new CglibProxyInterceptor());
// 创建代理对象
TargetClass proxyObject = (TargetClass) enhancer.create();
proxyObject.doSomething();
}
}
- 特点
优点:可以在运行时动态地创建代理对象,灵活性高。对于实现了相同接口的多个目标对象,可以使用相同的代理逻辑,减少代码冗余。
缺点:动态生成代理类的字节码会带来一定的性能开销。对于一些复杂的代理逻辑,实现起来可能比较复杂。
Java 中的代理有静态代理和动态代理两种主要实现方式。静态代理实现简单,但代码冗余度高;动态代理灵活性高,但有一定的性能开销。在实际应用中,可以根据具体的需求选择合适的代理方式。
- 上一篇: 详解Java中的静态代理和动态代理
- 下一篇: 详解 Java 中的变量
猜你喜欢
- 2024-12-13 Set的用法和实例详解——Java进阶知识讲义系列(五)
- 2024-12-13 阿里Java三面:分布式延时任务方案解析,万字长文一篇点通你
- 2024-12-13 Java快速处理图片的方式(总结)
- 2024-12-13 Java八股文面试全套真题【含答案】-反射篇
- 2024-12-13 java 如何一行代码生成随机数据?
- 2024-12-13 Java避坑指南——高并发场景下的性能隐藏杀手“UUID”
- 2024-12-13 反射java调用方法_java 使用反射调用方法
- 2024-12-13 详解 Java 中的变量
- 2024-12-13 详解Java中的静态代理和动态代理
- 2024-12-13 9分钟带你搞懂代理模式、静态代理、JDK+CGLIB动态代理
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)