Java代理模式(JDK Proxy)攻略
Java代理模式是一种非常常用的设计模式,它可以为某个对象提供一个代理对象,在代理对象中对目标对象进行增强、控制或者调整,而不用改变原有的对象和代码。该模式可以在不改变原有代码基础上,增强代码的功能和控制,从而实现特定的需求。
代理模式的使用场景
代理模式在实际开发过程中有着广泛的应用,一些常见的场景如下:
- 远程代理:即将对象的方法调用请求传递到远程,实现远程方法调用。
- 虚拟代理:在需要时,才创建目标对象,可提高对象实例化的效率。
- 安全代理:控制对目标对象的访问权限。
- 框架代理:框架实现中经常使用代理模式,例如Spring AOP中的切面就是基于代理模式的。
JDK Proxy的实现方式
在Java中,JDK Proxy是一种基于接口实现的代理模式,它要求被代理对象必须实现一个接口,用Proxy类去创建代理类对象。JDK Proxy代理模式的实现由以下几个步骤:
- 定义一个目标对象(申明一个接口)和与其相同的接口
- 创建代理实例Proxy.newProxyInstance()
- 将目标对象实例传递给代理实例
- 调用代理实例的方法
具体示例如下:
示例一:静态代理
我们定义一个接口Subject,代表一个被代理的对象,该对象有一个抽象方法doSomething(),然后定义一个目标对象RealSubject实现Subject接口,并实现doSomething()方法,最后定义一个代理类SubjectProxy,实现Subject接口,并调用RealSubject的doSomething()方法,在该方法中实现对RealSubject方法的增强,示例代码如下:
//定义抽象接口
public interface Subject {
void doSomething();
}
// 实现接口
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println("do something...");
}
}
//代理类
public class SubjectProxy implements Subject {
//代理的对象
private RealSubject realSubject;
public SubjectProxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void doSomething() {
System.out.println("before do something...");
realSubject.doSomething();
System.out.println("after do something...");
}
}
//调用示例
public class Main {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject subjectProxy = new SubjectProxy((RealSubject) realSubject);
subjectProxy.doSomething();
}
}
在上面的示例中,我们创建了一个代理类SubjectProxy,实现了Subject接口,并通过构造函数注入了实际执行任务的RealSubject对象,在实现doSomething()方法时,先执行了一些增强操作,再调用了RealSubject的doSomething()方法。这种静态代理模式非常简单明了,常用于单个简单的类的代理。
示例二:动态代理
在静态代理模式中,代理类的实现代码是写好的,不易于扩展或增加新的代理类。而动态代理可以在运行时动态生成代理类,可在同一接口上实现多个代理类,更便于扩展和维护。下面我们通过示例来解释动态代理的具体实现方式。
我们先定义一个接口Subject,代表一个被代理的对象,该对象有一个抽象方法doSomething(),然后定义一个目标对象RealSubject1实现Subject接口,并实现doSomething()方法,最后我们创建一个动态代理类DynamicProxy,继承java.lang.reflect.InvocationHandler接口,在DynamicProxy的构造方法中,将目标对象传入,然后实现InvocationHandler接口中的invoke()方法,在invoke()方法中,进行对目标对象方法的增强,示例代码如下:
// 定义抽象接口
public interface Subject {
void doSomething();
}
// 实现接口
public class RealSubject1 implements Subject {
@Override
public void doSomething() {
System.out.println("RealSubject1 do something...");
}
}
//动态代理类
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy (Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before do something...");
Object result = method.invoke(target, args);
System.out.println("after do something...");
return result;
}
}
//调用示例
public class Main {
public static void main(String[] args) {
Subject realSubject1 = new RealSubject1();
ClassLoader classLoader = realSubject1.getClass().getClassLoader();
Class<?>[] interfaces = realSubject1.getClass().getInterfaces();
DynamicProxy dynamicProxy = new DynamicProxy(realSubject1);
Subject subjectProxy = (Subject) Proxy.newProxyInstance(classLoader, interfaces, dynamicProxy);
subjectProxy.doSomething();
}
}
在上面的示例中,我们创建了一个动态代理类DynamicProxy,实现了InvocationHandler接口,通过InvocationHandler的invoke()方法,在进行RealSubject1的doSomething()方法调用前后,对其进行了增强,实现了代理的功能。
总的来说,动态代理和静态代理都是代理模式的实现方式,但动态代理能够更加灵活地实现代理,因此在实际开发中往往使用这种方式。值得注意的是,动态代理的性能较低,由于它是在运行时动态生成代理类,因此比静态代理慢一些。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java代理模式(jdk proxy) - Python技术站