代理模式概述
- 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用(接口的引用),可以做到在不修改目标对象的功能前提下,对目标功能扩展。
- 代理实现可以分为静态代理和动态代理。
静态代理(自己写代理类)
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。
![](https://img.haomeiwen.com/i3236595/49779a6ba342d98d.png)
- 抽象主题角色(Subject):可以是接口,也可以是抽象类
- 委托类角色(RealSubject):真实主题角色,业务逻辑的具体执行者
- 代理类角色(Proxy):内部含有对真实对象RealSubject的引用,负责对真实主题角色的调用,
interface Subject {
void request();
}
class RealSubject implements Subject {
public void request(){
System.out.println("RealSubject");
}
}
class Proxy implements Subject {
private Subject subject;
public Proxy(Subject subject){
this.subject = subject;
}
public void request(){
System.out.println("begin");
subject.request();
System.out.println("end");
}
}
public class ProxyTest {
public static void main(String args[]) {
RealSubject subject = new RealSubject();
Proxy p = new Proxy(subject);
p.request();
}
}
动态代理(JVM动态创建代理类)
- 因为静态代理对象需要与目标对象实现一样的接口,所以会有很多代理类,一旦接口增加方法,目标对象与代理对象都要维护。所以动态的生成代理类就解决此问题。
- 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
interface Subject {
void request();
}
class RealSubject implements Subject {
public void request(){
System.out.println("RealSubject");
}
}
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 {
Object result = method.invoke(target, args);
return result;
}
/**
*创建动态代理的对象,需要借助 Proxy.newProxyInstance。该方法的三个参数分别是:
*ClassLoader loader表示当前使用到的appClassloader。
*Class<?>[] interfaces表示目标对象实现的一组接口。
*InvocationHandler h表示当前的InvocationHandler实现实例对象。
*/
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
public class Client{
public static void main(String[] args) {
DynamicProxy proxy = new DynamicProxy( new RealSubject());
Subject subject = proxy.getProxy<Subject>();
subject.visit();
}
}
动态代理自动生成代理类
public final class $proxy1 extends Proxy implements Subject{
public $proxy1(InvocationHandler invocationhandler) {
super(invocationhandler);
}
public final void request() {
try {
super.h.invoke(this, m3, null);
return;
}
catch(Error _ex) { }
catch(Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
static {
try {
m3 = Class.forName("xxxx.Subject").getMethod("request", new Class[0]);
m1 = ...
...
}
catch(NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
}
catch(ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
...
}
- 生成的$proxy1继承自Proxy类,并实现了Subject接口。
- 执行代理对象的方法,其实就是执行InvocationHandle对象的invoke方法,传入的参数分别是当前代理对象,当前执行的方法和参数。
- 通过反射类Proxy和InvocationHandler回调接口实现的jdk动态代理,要求委托类必须实现一个接口,对于没有实现接口的类,便无法使用该方方式实现动态代理。
网友评论