动态代理的优点:
- 动态代理能够增加程序的灵活度(eg:加入方法执行前后的判断)
- 完美解决耦合问题,动态代理可以将调用层和实现层分离(eg:retorfit网路请求)
- 动态代理不需要接口的实现类(eg:ipc进程通讯,将方法调用转成其他逻辑)
- 动态代理可以解决程序执行流程的问题。
动态代理的含义
定义:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。
作用:通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给对象系统带来不必要复杂性。
为什么会有动态代理
传统面向对象中,如果想要实现功能的复用,要么继承,要么引用,但是无论哪种方式,
对代码都有一定的浸入性,耦合无可避免。
浸入性含义:
如果你想用它增强你程序的功能,你必须改动现有程序的代码,那它就具有侵入性。如果只是一点两点需要增强还好,
如果大量的功能点需要被增强,工作量就会很大,代码也不太优雅。想象一下如果你对外公开的一系列的接口,
要添加一个权限控制,那样你就需要对每个接口都来校验一边。这就可以看出面向对象思想的短板,要为程序
新增一些通用功能,只能通过耦合的方式才能进行。AOP正式为了解决这个问题而生,AOP是通过一种无耦合的
方式来为程序带来增强。而动态代理就是AOP的一种实现方式
动态代理应用的场景
- 权限集中申请
- 日志集中打印
- 底层屏蔽具体网络请求(retorfit网络请求)
- RPC远程过程调用
- 需要对较难修改的类方法进行功能增强
Android中动态代理的实现方式
- Java Proxy(接口实现)
- AspectJ 备注:Cglib(只能java用,Android用不了)
Java Proxy代理的示例代码
首先需要有一个接口
public interface HelloInterface {
void sayHello();
}
其次需要有一个实现类
public class HelloImpl implements HelloInterface{
@Override
public void sayHello() {
System.out.println(">>>>>>>>sayHello<<<<<<<<<<<");
}
}
最后调用的代码
public static void main(String[] args) {
HelloImpl hello=new HelloImpl();
HelloInterface helloInterface = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(), new ProxyHandler());
helloInterface.sayHello();
}
static class ProxyHandler implements InvocationHandler{
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("arrom>>>>>>>>>>>>>>调用");
return null;
}
}
大致的调用过程如图:
源码分析:
//生成一个运行时对象
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, (Class[])interfaces.toArray(Proxy.EMPTY_CLASS_ARRAY), accessFlags);
ProxyGenerator能够在运行时生成一个对象,而且这个对象是实现了该接口。这个对象所属的类是一个全新的class。Class需要生成才能加载,而ProxyGenerator在运行时,是生成class字节码,并且加入内存。