Android 静态代理和动态代理

本文详细解析了Android中静态代理和动态代理的概念及应用。通过示例代码,展示了如何使用代理模式来增强对象的功能,同时介绍了动态代理的实现机制,包括InvocationHandler和Proxy类的作用。
摘要由CSDN通过智能技术生成

Android 静态代理和动态代理

代理模式定义:为其他对象提供一种代理以控制这个对象的访问

静态代理

静态代理比较简单,看下下面的代码就很好理解

//定义一个接口
public interface Subject {
    void sayGoodBye();
    void sayHello(String str);
}
//定义一个被代理的类
public class RealSubject implements Subject {
    @Override
    public void sayGoodBye() {
        System.out.println("RealSubject sayGoodBye");
    }

    @Override
    public void sayHello(String str) {
        System.out.println("RealSubject sayHello  " + str);
    }
}
//代理类
public class ProxySubject implements Subject {

    private Subject subject;

    public ProxySubject(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void sayGoodBye() {
        //代理类,功能的增强
        System.out.println("ProxySubject sayGoodBye begin");
        //在代理类的方法中 间接访问被代理对象的方法
        subject.sayGoodBye();
        System.out.println("ProxySubject sayGoodBye end");
    }

    @Override
    public void sayHello(String str) {
        //代理类,功能的增强
        System.out.println("ProxySubject sayHello begin");
        //在代理类的方法中 间接访问被代理对象的方法
        subject.sayHello(str);
        System.out.println("ProxySubject sayHello end");
    }
}

使用方法

//被代理对象,某些情况,我们不希望修改已有代码,我们采用代理来间接访问
RealSubject realSubject = new RealSubject();
//代理类对象
ProxySubject proxySubject = new ProxySubject(realSubject);
proxySubject.sayGoodBye();
proxySubject.sayHello("Test");

输出结果
ProxySubject sayGoodBye begin
RealSubject sayGoodBye
ProxySubject sayGoodBye end
ProxySubject sayHello begin
RealSubject sayHello Test
ProxySubject sayHello end

动态代理

动态代理也叫做jdk代理、接口代理,不需要实现目标对象的接口。生成代理对象,使用的是Java的API,动态的在内存中构建代理对象。

1、在java的动态代理机制中,有两个重要的类或接口
一个是 InvocationHandler(Interface)
另一个则是Proxy(Class)
这一个类和接口是实现我们动态代理所必须用到的
2、 InvocationHandler

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

proxy:指代生成的代理对象;
method:指代的是我们所要调用真实对象的某个方法的Method对象;
args:指代的是调用真实对象某个方法时接受的参数;

每一个代理实类例的invocation handler都要实现InvocationHandler这个接口。并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke 方法来进行调用

3、 Proxy这个类的 newProxyInstance 这个方法
JDK动态代理需要借助接口来实现,如果我们要代理的对象功能没有抽成任何接口,那么我们就无法通过JDK动态代理的方式来实现。

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。

第一步:定义一个接口
//定义一个接口
public interface Subject {
    void sayGoodBye();
    void sayHello(String str);
}
第二步:定义真是对象(被代理类):
//定义一个被代理的类
public class RealSubject implements Subject {
    @Override
    public void sayGoodBye() {
        System.out.println("RealSubject sayGoodBye");
    }

    @Override
    public void sayHello(String str) {
        System.out.println("RealSubject sayHello  " + str);
    }
}
第三步: 定义一个InvocationHandler, 相当于一个代理处理器

SubjectInvocationHandler并不是真正的代理类,而是用于定义代理类需要扩展、增强那些方法功能的类。在invoke函数中,对代理对象的所有方法的调用都被转发至该函数处理。在这里可以灵活的自定义各种你能想到的逻辑。

public class SubjectInvocationHandler implements InvocationHandler {
    //这个就是我们要代理的真实对象
    private Object subject;
    //构造方法,给我们要代理的真实对象赋初值
    public SubjectInvocationHandler(Object subject) {
        this.subject = subject;
    }
    @Override
    public Object invoke(Object object, Method method, Object[] args) throws Throwable {
        //在代理真实对象前我们可以添加一些自己的操作
        System.out.println("before Method invoke");
        System.out.println("Method:" + method);
        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        method.invoke(subject, args);
        //在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("after Method invoke");
        return null;
    }
}
第四步:调用
//被代理类
Subject realSubject = new RealSubject();
//我们要代理哪个类,就将该对象传进去,最后是通过该被代理对象来调用其方法的
SubjectInvocationHandler handler = new SubjectInvocationHandler(realSubject);
//生成代理类
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
                                                          realSubject.getClass().getInterfaces(), handler);
//输出代理类对象
System.out.println("Proxy : "+ subject.getClass().getName());
System.out.println("Proxy super : "+ subject.getClass().getSuperclass().getName());
System.out.println("Proxy interfaces : "+ subject.getClass().getInterfaces()[0].getName());
//调用代理类sayGoodBye方法
subject.sayGoodBye();
System.out.println("--------");
//调用代理类sayHello方法
subject.sayHello("Test");
   结果:
   Proxy super : java.lang.reflect.Proxy
    Proxy interfaces : com.company.ha.Subject
    before Method invoke
    Method:public abstract void com.company.ha.Subject.sayGoodBye()
    RealSubject sayGoodBye
    after Method invoke
    --------
    before Method invoke
    Method:public abstract void com.company.ha.Subject.sayHello(java.lang.String)
    RealSubject sayHello  Test
    after Method invoke
总结:

与静态代理相比,动态代理具有如下的优点:

1.代理转发的过程自动化了,实现自动化搬砖;
2.代理类的代码逻辑和具体业务逻辑解耦,与业务无关;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值