Android开发Android开发经验谈Android知识

2017-10-4(动态代理)

2017-10-06  本文已影响64人  721d739b6619

代理分为静态代理和动态代理。

/**
 * 静态代理中代理类和委托类也常常继承同一父类或实现同一接口。
 * 普通业务类
 * 通过接口更加灵活实现代理模式
 */
public interface Subject {

    void visit();

}

/**
 * 委托类
 * 代理类和真实业务类都需要实现业务类的接口
 */
public class RealSubject implements Subject{
    @Override
    public void visit() {
        //真实业务具体逻辑
        System.out.println("Real Subject");
    }
}

/**
 * 代理类
 * 代理类和委托类都需要实现业务类的接口
 */
public class ProxySubject implements Subject {

    private Subject iSubject;//委托类

    public ProxySubject(Subject subject){
        //关键:关联委托类
        this.iSubject = subject;
    }

    @Override
    public void visit() {
        //调用真实业务类的方法
        iSubject.visit();
    }
}

public class Client {

    public static void main(String[] args){
        //构造一个真实主题对象
        RealSubject realSubject = new RealSubject();

        //通过真实主题对象构造一个代理对象
        ProxySubject proxySubject = new ProxySubject(realSubject);

        //调用代理类的相关方法
        proxySubject.visit();
    }
}

其实可以看个几个关键点:

其实静态代理:在实际中不方便直接构建委托对象,而需要代理类实现具体的方法。

public interface DynamicInterface {
    //实现逻辑
    void implement();
}

/**
  委托类
 * 实现接口
 */
public class DynamicRealSubject implements DynamicInterface{

    @Override
    public void implement() {
        Log.e("DynamicRealSubject","DynamicRealSubject___动态代理模式");
    }
}

/**
 * 实现InvocationHandler的类是运行时将生成的代理类需要完成的具体任务即invoke方法里面
 * 动态代理
 */
public class DynamicProxySubject implements InvocationHandler{

    private Object sub;//需要被代理的对象

    public DynamicProxySubject(Object sub){
        this.sub = sub;
    }

    public DynamicProxySubject(){}


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Log.e("DynamicProxySubject","动态代理前");

        //真正被代理类的方法被调用 method就是被代理的类的方法
        method.invoke(sub,args);
        //proxy这个参数在方法里写会内存溢出
//        method.invoke(proxy,args);
        Log.e("DynamicProxySubject","动态代理后");
        return null;
    }
}


//实现结果
 public static void main(String[] args) throws Exception {
        DynamicRealSubject realSubject = new DynamicRealSubject();

        InvocationHandler handler = new DynamicProxySubject(realSubject);
    

        //一次性生成
        DynamicInterface subject = (DynamicInterface)Proxy
                .newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),handler);
       

        //实现动态代理被代理类的方法
        subject.implement();
    }

动态代理与静态代理最大的不同就是代理类非程序员预先定义好,而是在运行时才生成代理类。

提示:
我开始时候以为实现InvocationHandler接口的就是代理类,其实是错误的。该类其实提供给Proxy类构造时关联用到的。每当生成代理类实例调用代理方法就会调用实现InvocationHandler接口的类中的invoke方法。

实现InvocationHandler接口的类

看看这个InvocationHandler类到底如何与Proxy有联系的

DynamicRealSubject realSubject = new DynamicRealSubject();
InvocationHandler handler = new DynamicProxySubject(realSubject);
Class cls = realSubject.getClass();
 DynamicInterface subject = 
(DynamicInterface)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),handler);          

这样就将InvocationHandler类与Proxy类关联起来。
看看Proxy.newProxyInstance这个方法是做什么的

newProxyInstance方法内部

看到了cl这个变量明显就是一个类对象然后在生成构造函数再构建对象。构建对象时通过h即InvocationHandler这个实例关联一起。整个过程就是这样生成一个代理实例。

看看getProxyClass0方法生成类对象


Paste_Image.png

由于该方法太长截取关键部分:
这里的generateProxy就是生成类对象,之前的代码是进行缓存。

看看生成代理对象那代码:

Paste_Image.png Paste_Image.png

生成代理对象时,把InvocationHandler实例传进去
所以它最终生成的代理类是会有InvocationHandler的痕迹的。这里我看了网上的说,生成的代理类是继承Proxy实现委托接口。在代理方法里面InvocationHandler通过反射调用invoke方法。

上一篇 下一篇

猜你喜欢

热点阅读