代理模式

代理模式

定义:为另一个对象提供一个替身来控制对这个对象的访问。

用现实中的场景来举例,比如我要租一个房子,但是我没有门路可以直接找到房东,所以我找了一个中介来帮我租个房子。但是中介也不能白干活啊,所以在租房子后,他就需要向我收取中介费。

在这个例子中,中介就是代理,房东是我们真实需要的对象(房子由房东提供,而我需要一个房子)。

用UML图表示:
这里写图片描述

代理分为动态代理和静态代理,这里的动态和静态是对于代理类何时生成来定义的。

静态代理是需要我们手动写好代理类,以及他的各种行为,然后在编译的时候就生成代理类

动态代理则是通过反射,在运行时生成代理类。

静态代理实现

//接口
public interface Lentable {
    void lent(String clientName);
}
//中介
public class Agency implements Lentable {

    private Lentable intermediary;

    public Agency(Lentable intermediary) {
        this.intermediary = intermediary;
    }

    @Override
    public void lent(String clientName) {
        System.out.println("带"+clientName+"看房子");
        intermediary.lent(clientName);
        System.out.println("向"+clientName+"收取中介费");
    }
}
//房东
public class Intermediary implements Lentable {
    @Override
    public void lent(String clientName) {
        System.out.println("将房子出租给"+clientName);
    }
}

输出结果
这里写图片描述

动态代理实现

动态代理有两种实现方式,一种是jdk自带的动态代理,另外一种是cglib。

jdk动态代理

接口和房东的实现不变,中介实现InvocationHandler接口,而不是Lentable接口。
jdk的动态代理是面向接口的,将具体实现和调用解耦了。

//中介
public class Agency implements InvocationHandler {
    //接受真实的房东对象
    private Lentable intermediary;

    public Agency(Lentable intermediary) {
        this.intermediary = intermediary;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("带"+args[0]+"看房子");
        method.invoke(intermediary,args);
        System.out.println("向"+args[0]+"收取中介费");
        return null;
    }
}
// 客户端调用

Intermediary intermediary = new Intermediary();
InvocationHandler agency =  new Agency(intermediary);
//使用Proxy生成代理类
Lentable lentable = (Lentable) Proxy
    .newProxyInstance(Lentable.class.getClassLoader(),new Class[]{Lentable.class},agency);
//客户端通过这个代理类去租房子,代理类会再通过反射调用真实业务类的方法。
lentable.lent("arry");

Cglib动态代理

Cglib是基于具体类实现的,所以不需要Lentable接口。
这里创建的动态代理类其实是具体业务类的子类。

// 中介类
public class Agency implements MethodInterceptor {

    private Intermediary intermediary;

    public Object getInstance(Intermediary intermediary){
        this.intermediary = intermediary;  //给业务对象赋值
        Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
        enhancer.setSuperclass(this.intermediary.getClass());  //指定要代理的业务类
        //所有对代理对象对调用都会通过这里的intercept进行拦截,以实现对真实对象的调用
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("带"+args[0]+"看房子");
        method.invoke(intermediary,args);
        System.out.println("向"+args[0]+"收取中介费");
        return null;
    }

}
//客户端调用
Agency agency = new Agency();
Intermediary intermediaryProxy = (Intermediary) agency.getInstance(new Intermediary());
intermediaryProxy.lent("arry");

区别

JDK通过接口的方法名调用被代理类的方法。所以被代理类必须实现一个接口,才能生成代理类。

cglib则是针对被代理类生成子类,然后在子类中调用被代理类的方法。所以这里被代理的类不能声明为final。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值