- 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
动态代理的角色和静态代理的一样 .
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
动态代理分为两类 :
一类是基于接口动态代理 , 一类是基于类的动态代理
- 基于接口的动态代理----JDK动态代理
- 基于类的动态代理–cglib
现在用的比较多的是 javasist 来生成动态代理
我们这里使用JDK的原生代码来实现
【1】. javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
核心 : InvocationHandler类 和 Proxy 类
Object invoke(Object proxy, 方法 method, Object[] args);
//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
现在我们通过动态代理模式来实现我们在静态代理中所写实例。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//真实角色: 购票者,购票者需要购票
public class TicketBuyer implements ITicketPurchase{
@Override
public void buyTicket() {
System.out.println("已经买到票了!");
}
public static void main(String[] args) {
//真实角色:购票者的角色,他实现了 购票 的接口;真实角色只需要关注 购票即可,
//而不需要去关注购票的具体过程,即将大象塞进冰箱一样,我们只提供三步即可!
TicketBuyer ticketBuyer = new TicketBuyer();
//代理实例的调用处理程序;
//可以理解为 购票窗口
BuyTicket buyTicket = new BuyTicket();
//代理对象需要知道他为谁而代理,即我们去窗口买票的时候,需要提供身份证
buyTicket.setTicketBuyer(ticketBuyer); //将真实角色放置进去!
//创建一个代理的对象,让代理对象去帮我们处理购票的具体过程
//可以理解为具体的 操作员
ITicketPurchase proxy = (ITicketPurchase)buyTicket.getProxy(); //动态生成对应的代理类!
//操作员 去执行 具体的购票流程
proxy.buyTicket();
}
}
//抽象角色: 购票
interface ITicketPurchase{
void buyTicket();
}
//代理角色 : 购票站
class BuyTicket implements InvocationHandler {
private TicketBuyer ticketBuyer;
public void setTicketBuyer(TicketBuyer ticketBuyer) {
this.ticketBuyer = ticketBuyer;
}
//生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
ticketBuyer.getClass().getInterfaces(),this);
}
// proxy : 代理类 method : 代理类的调用处理程序的方法对象.
// 处理代理实例上的方法调用并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
//核心:本质利用反射实现!
//回去执行被代理对象的方法,即执行购票者ticketBuyer的 buyTicket()方法,并且返回该方法的值;
Object result = method.invoke(ticketBuyer, args);
after();
return result;
}
//购票之前
private void before() {
System.out.println("查询是否有票...");
System.out.println("提交购票申请...");
System.out.println("付钱...");
System.out.println("出票...");
}
//完成购票之后
private void after() {
System.out.println("打印发票,提供给购票者!");
}
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!
如果我们需要编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!
可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
公共的业务由代理来完成 . 实现了业务的分工 ,
公共业务发生扩展时变得更加集中和方便 .
一个动态代理 , 一般代理某一类业务
一个动态代理可以代理多个类,代理的是接口!
动态代理模式 狂神说