您的位置:首页 > 职场人生

黑马程序员——静态代理与动态代理

2014-11-16 13:35 141 查看
一、什么是代理

Java的代理模式在生活是非常常见的,比如一个人去租房子,可以去找房屋中介,也可以去找房子的主人,最终的目的是租到房子。两种方式都可以解决问题,中介就相当于一个代理,找它解决可能会更省时省力。在Java编程中使用代理模式,目的就是为其他对象提供一个代理以控制对某个对象的访问。代理模式涉及到三个角色:

(1)抽象角色:声明真实角色的接口。

(2)真实角色:抽象角色的实现。

(3)代理角色:代理角色内可以含有对真实角色的引用,同时可以实现一些附加操作。

二、静态代理

静态代理就是简单的将真实角色中的方法重新实现,重载抽象类中声明的方法。

抽象角色:

public interface subject {
public void request();

}


真实角色:

public class realsubject implements subject {

@Override
public void request() {
System.out.println("From real subject!");

}

}


代理角色:

public class proxysubject implements subject {

@Override
public void request() {
new realsubject().request();
System.out.println("This is proxy!");

}
}


测试文件:

public class proxyClient {
public static void main(String[] args) {
subject sub=new proxysubject();
sub.request();
}
}


运行结果:

From real subject!

This is proxy!

从运行结果中可以看到,执行了真实角色的方法之后,又执行了自己的部分,就是打印“This is proxy”。这就相当于房屋中介在帮你在找到房子之后,会收取中间费用一样。静态代理缺点明显,代理角色和真实角色一一对应,这样对每一个类,都要有一个代理类与之对应,这样代码的复用率就下降,而动态代理可以很好的解决这一问题。

三、动态代理

Java动态代理机制的出现,使的Java开发人员不用手工编写代理类,只要简单的指定一组接口及委托类对象,便能动态的获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。Java动态代理具体有如下四个步骤:

(1)通过实现InvocationHandler接口创建自己的调用处理器。

(2)通过为Proxy类指定ClassLoader对象和一组Interface来创建动态代理类。

(3)通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型。

(4)通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

抽象角色:

public interface Subject {
public void show();
}

真实角色:

public class RealSubject implements Subject {
public void show() {
System.out.println("From Real Subject");
}
}

代理角色:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//实现 InvocationHandler接口创建自己的调用处理器
public class ProxySubject implements InvocationHandler {
private Object sub;
public ProxySubject(Object obj){
sub=obj;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before calling:"+method);
method.invoke(sub, args);
System.out.println("after calling:"+method);
return null;
}
}


测试文件:

import java.lang.reflect.*;

public class Client {

public static void main(String[] args) {
RealSubject realsub=new RealSubject();
InvocationHandler handler=new ProxySubject(realsub);
Class<?> classType=handler.getClass();
//newProxyInstance()用于为指定类加载器、一组接口及调用处理器生成动态代理类实例
Subject sub=(Subject)Proxy.newProxyInstance(classType.getClassLoader(),RealSubject.class.getInterfaces(),handler);
sub.show();
}
}


执行结果:

before calling:public abstract void dynamicproxy.Subject.show()

From Real Subject

after calling:public abstract void dynamicproxy.Subject.show()

执行的过程是这样的:

sub.show()------>handler.Invoke()------>realsub.show()

再回头来看动态代理,用的是最基本的Object类,根本就没有与Subject类绑定,因此它可以作为所有从Object衍生出的子类的代理,即一对多的代理,极大的提高了代码的复用率。上面的这种动态代理叫做jdk proxy即原生的jdk代理,它其实不是完美的,只能代理实现了接口的类,要想完成对类本身实现代理,就需要用到另外一个开源的类库cglib。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: