Java设计模式之代理(动态代理,静态代理)

代理设计模式,是一种常用的设计模式。顾名思义,在面向对象的世界中,就是一个对象对另一个对象的代理。

如现实生活中,处处都是代理,中介是对业主的代理,王婆是对金莲的代理,经纪人至于艺人的代理,销售代理等,当然这是通俗代理。

代理对外是代理对象去交互,但是真正完成工作的,往往又是被代理的对象。例如租房,找中介,但是真正租到的是业主的房子。xxx找王婆,但是最终干活的是金莲。找艺人拍戏,找的是经纪人,但最终拍戏的是艺人等等。

为什么要这样做呢?

对于代理对象,提供比较单一的功能,且可以在代理增加需要的逻辑,却不影响被代理对象。如经纪人帮艺人包装等。

对于被代理对象,控制被代理对象的访问权限,被代理对象只提供部分需要的功能。如中介只代理业主的房子。如果啥都让业主做的话,业主的事情会非常多,而表现在程序上,就是对象的功能非常复杂。

在程序设计模式中,代理模式又可以分为静态代理,动态代理。

静态代理

通过代码来熟悉静态代理,下面是一个静态代理的例子,首先有个IPrettyGirl接口,有三个方法chat,enjoy,sleep三个方法

public interface IPrettyGirl {

    void chat();

    void enjoy();

    void sleep();
}

接口有一个实现

public class JinLian implements IPrettyGirl {
    @Override
    public void chat() {
        System.out.println("to chat with "+this.getClass().getSimpleName());
    }

    @Override
    public void enjoy() {
        System.out.println("to enjoy with "+this.getClass().getSimpleName());
    }

    @Override
    public void sleep() {
        System.out.println("to sleep with "+this.getClass().getSimpleName());
    }
}

有一个代理类Wangpo,代理IPrettyGirl的chat和enjoy方法。毕竟sleep是违法的,不能做这事。

public class WangPo {

    private IPrettyGirl prettyGirl;

    public WangPo(IPrettyGirl prettyGirl){
        this.prettyGirl = prettyGirl;
    }

    public void chat(){
        this.prettyGirl.chat();
        System.out.println("I am "+this.getClass().getSimpleName()+", I Completed a chat order");
    }

    public void enjoy(){
        this.prettyGirl.enjoy();
        System.out.println("I am "+this.getClass().getSimpleName()+", I Completed a enjoy order");
    }
}

这时候大官人要来找乐子了,怎么找呢,不用找金莲,有武松在太危险了,直接找王婆就可以了。

public class XiMenDaGuanRen {

    public static void main(String[] args) {
        IPrettyGirl prettyGirl = new JinLian();
        WangPo wangPo = new WangPo(prettyGirl);
        wangPo.chat();
        wangPo.enjoy();
    }
}

这样就实现了一个经典的静态代理,通过面向接口编程,王婆可以代理所有的漂亮女孩(实现了IPrettyGir接口的对象)。但是为什么是静态代理呢,因为这中代理,要找女孩的话,需要提前的编写代理类去代理IPrettyGirl的对象。这样的话,在某些情况下,也是不方便的。这个时候就需要动态代理了。

动态代理

同样通过代码和实例理解什么是动态代理。西门大官人整天找王婆,难免会让旁人发现问题。但是大官人还是要找乐子,如果自己重新找个代理就好了。这个时候就可以用动态代理,自己创建代理,就可以随时享乐了。

public class XiMenDaGuanRen {

    public static void main(String[] args) {
        IPrettyGirl prettyGirl = (IPrettyGirl) Proxy.newProxyInstance(XiMenDaGuanRen.class.getClassLoader(), new Class[]{IPrettyGirl.class}, new ProxyInvocationHandler(new JinLian()));
        prettyGirl.chat();
        prettyGirl.enjoy();
    }
}

class ProxyInvocationHandler implements InvocationHandler{

    private Object object;

    public ProxyInvocationHandler(Object obj){
        this.object = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before service");
        Object obj = method.invoke(this.object, args);
        System.out.println("after service");
        return obj;
    }
}

动态代理有一套特定的API,动态代理不需要编写特定的代理类,可以使用代码动态创建代理类,只需要知道代理类的对象和类型即可。现在对代理,静态代理,动态代理应该有了初步的了解了。

再来看看JDK动态代理涉及到的Java API

Proxy,提供创建动态代理类和对象的静态方法,也是这些方法创建的所有动态代理类的超类。

InvocationHandler,代理类实例的Invocation Handler实现的接口。每一个代理类的实例,都有一个关联的调用处理程序,调用代理实例的invoke方法时,方法调用会被转发到代理实例InvocationHandler来执行。

cglib动态代理

上面这些是JDK的动态代理,第三方库cglib也提供了动态代理的实现方式,再了解一下cglib的动态代理。

通过代码来了解一下,直接看怎么使用cglib实现动态代理。

public class XiMenDaGuanRen {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(JinLian.class);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("before service");
                Object obj = methodProxy.invokeSuper(o, objects);
                System.out.println("before service");
                return obj;
            }
        });
        JinLian jinLian = (JinLian) enhancer.create();
        jinLian.enjoy();
        jinLian.chat();
    }
}

看起来大同小异,cglib的关键api,cglib相比较jdk的动态代理,可以代理类,而jdk只能代理接口。

Enhancer,生成动态子类以实现方法拦截,最初是作为JDK1.3自带动态代理的另外一种支持,带允许扩展具体的基类,也可以实现接口,动态生成的子类,重写父类的非final方法,并回调到用户自定义的拦截器。

MethodInterceptor,方法拦截器,代理类的CallBack实现的接口,代理类的方法调用被转发到回调来执行。

(^_^)

 

你可能感兴趣的:(Java)