Java代理模式

2017-10-29  本文已影响16人  流云飞鸟
什么是代理模式:

代理模式是23种设计模式中的一种,其思想是:为目标对象提供代理,外部想要访问目标对象就必须通过代理,这样做的意义在于隔离目标对象,比如 明星跟经纪人,就是很典型的代理模式,明星就是目标,经纪人就是代理,现在有一家公司想要找明星拍广告,怎么办,能直接找这个明星吗,不能,那就去找他的代理(经纪人)吧,具体经纪人如何跟明星商量的,广告公司不用管。画个图:


代理模式.png
三种代理模式:

1. 静态代理:
首先我们定义一个目标对象和代理对象的公共接口(保证在使用者看来,貌似我就是调用了目标对象的方法)

public interface IStart {
    void advertising();
}

接下来,我们定义一个目标类

public class Star implements IStart {
    String name;

    public Star(String name) {
        super();
        this.name = name;
    }

    // 拍广告
    @Override
    public void advertising() {
        System.out.println("我是" + name + ",我给你拍霸王洗发水的广告");
    }
}

代理类:

public class StarProxy implements IStart {
    //我是代理类,我在创建的时候就要给我指定,我要代理谁
    private Star star;
    public StarProxy(Star star) {
        super();
        this.star = star;
    }

    @Override
    public void advertising() {
        star.advertising();
    }
}

好了,所有类都定义好了,我们开始使用

public static void main(String[] args) {
        Star star = new Star("成龙");
        StarProxy proxy = new StarProxy(star);
        //拍广告
        proxy.advertising();
    }

输出结果:我是成龙,我给你拍霸王洗发水广告,是不是很简单呢,对于使用者来说,我调用的是代理对象的方法,但是真正做事的还是目标对象
大家有没有发现,我的代理类和目标类都实现了同一个接口,IStar,那么如果我现在有新的功能来了,比如,我不仅拍广告,我还可以拍电影,我还可以唱歌,如果添加,那么目标类和代理类都需要维护,这就麻烦了,没关系,下面我们看看动态代理


2. 动态代理
动态代理的代理对象不需要实现接口,动态代理的核心类:java.lang.reflect.Proxy,代理对象的生成一般通过
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法来生成的,需要三个参数:

  1. ClassLoader 目标对象的类加载器
  2. interfaces[] 目标对象所实现的所有接口,可以是一个也可以是多个
  3. InvocationHandler 事件处理的方法(android中的handler有点像,反正只要知道,他是处理事件的,下文会有代码)
    我们直接上代码,Star和IStar都不用换,创建StarProxy2
public class StarProxy2 {
    Star star;

    public StarProxy2(Star star) {
        super();
        this.star = star;
    }
    public Object getProxy(){
        return Proxy.newProxyInstance(star.getClass().getClassLoader(), star.getClass().getInterfaces(), new InvocationHandler() {
            
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                //下面代码invoke(),是不是很熟悉,没错,就是反射
                Object returnObj = method.invoke(star, args);
                return returnObj;
            }
        });
        
    }
}

public static void main(String[] args) {
        Star star = new Star("成龙");
        StarProxy2 proxy2 = new StarProxy2(star);
        IStart iStart = (IStart) proxy2.getProxy();
        iStart.advertising();
    }

动态代理和静态代理的区别是,动态代理中,代理类不用实现接口,共同点是目标类需要实现接口,那么有没有目标类和代理类都不用实现接口的代理方式呢,有!哈哈,这就是我们接下来要说的,Cglib代理


3. Cglib代理(这里仅介绍用法)先去github下载Cglib,他还要依赖asm和ant所以都要分别下载

Cglib又叫子类代理,为什么呢,其原理就是在内存中创建目标对象的子类作为代理类。他的用途很广泛,例如 Spring AOP。

//新建一个类,我这里叫StarProxy3,实现MethodInterceptor,这个接口就是来处理代理的方法
public class StarProxy3 implements MethodInterceptor{
    Star star;

    public StarProxy3(Star star) {
        super();
        this.star = star;
    }
    public Object getProxy(){
        //这是一个工具,我们告诉他目标对象的Class,因为一会他要给他创建一个子类
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(star.getClass());
        //这里是设置回掉接口,就是我们实现MethodInterceptor的方法intercept;
        enhancer.setCallback(this);
        //开始创建代理类了
        return enhancer.create();
        
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
         //通过反射调用,和动态代理一样
        Object returnObj = method.invoke(star, args);
        return returnObj;
    }
}


public static void main(String[] args) {
        Star star = new Star("成龙");
        //这里的proStar实际是Star类的子类
        Star proStar = (Star) new StarProxy3(star).getProxy();
        proStar.advertising();
        
        
    }

注:这里有一个小细节,被代理的类一定要保证有空参构造,因为Cglib代理就是通过目标类的空参构造来创造其子类,并为其代理,若没有,则会报错

总结:三种代理方式,做android开发一般Cglib用的不多(我是这样子的,因为比较麻烦),一般第二种就完全搞定了,想研究Cglib源码的童鞋可以点这里

上一篇下一篇

猜你喜欢

热点阅读