一.先说明一下设计模式中代理模式是什么?
代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性
首先我模拟一个场景,公司领导发奖金给员工的行为,我希望作为公司领导只关注发多少奖金,具体发给谁,是因为什么原因发,这些领导可以不用管,在这种情况下,就可用代理类去代理领导发奖金,他去过滤员工,具体每个发多少奖金;首先领导的这种行为可抽象为
interface person{
void giveBonus(int value)
}
二.java的代理分为两类,根据创建代理类的时间点,又可以分为静态代理和动态代理。
1.静态代理:指的是在compile时已经将接口,被代理类,代理类等确定下来。在程序runtime之前,代理类的.class文件就已经生成。AOP 编程就是基于动态代理实现的
//被代理类
class Leader implements person{
void giveBonus(int value){
sysout("银行转账"+value+“元”)
}
}
代理类
class LeaderProxy implements person{
private Leader leader;
LeaderProxy(Leader leader){
this.leader = leader
}
void giveBonus(int value){
leader.giveBonus(value)
}
}
main(){
LeaderProxy delegate = new LeaderProxy(new Leader())
delegate.giveBonus(100)
}
2.动态代理:代理类在程序runtime创建的代理方式被成为动态代理
public class MyInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
T target;
public MyInvocationHandler(T target) {
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" +method.getName() + "方法之前"+currenttime);
Object result = method.invoke(target, args);
System.out.println("代理执行" +method.getName() + "方法之后"+currenttime);
return result;
}
}
main(){
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler leaderHandler = new MyInvocationHandler<person>(leader);
//创建一个代理对象stuProxy,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
person leaderProxy= (person) Proxy.newProxyInstance(person.class.getClassLoader(), new Class<?>[]{person.class}, leaderHandler);
}
三.cglib
JDK的动态代理 代理的是接口,也就是你的 业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。cglib是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,cglib是一个好的选择。
cglib的缺点是:cglib底层采用ASM字节码生成框架,使用字节码技术生成代理类,也就是生成的.class文件,而我们在android中加载的是优化后的.dex文件,也就是说我们需要可以动态生成.dex文件代理类,cglib在android中是不能使用的。但后面我们会根据dexmaker框架来仿照动态生成.dex文件,实现cglib的动态代理功能。