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

来源:互联网 发布:二手警服淘宝 编辑:程序博客网 时间:2024/05/16 01:50

一、什么是代理

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

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

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

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

二、静态代理

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

抽象角色:

public interface subject {public void request();}


真实角色:

public class realsubject implements subject {@Overridepublic void request() {System.out.println("From real subject!");}}


代理角色:

public class proxysubject implements subject {@Overridepublic 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;}@Overridepublic 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。

 

0 0
原创粉丝点击