一探究竟代理模式

代理模式

代理模式概念

代理模式(Proxy Pattern)是指为其他对象提供一种代理,控制对这个对象的访问,属于结构型模式。

代理模式一般包含三种角色
  1. 抽象主题角色(Subject):抽象主题类的主要职责是声明真实主题与代理的共同接口方法,该类是以接口也可以是抽象类;
  2. 真实主题角色(RealSubject):该类被称为代理类,该类定义了代理所表示的真实对象,是负责执行系统真正的逻辑业务对象;
  3. 代理主题角色(Proxy):被称为代理类,内部持有RealSubject的引用,具备完全的对RealSubject的代理权,客户端调用代理对象的方法,同时也调用被代理对象的方法,但是会在代理对象前后增加一些处理代码;

代理一般就是被理解为代码的增强,就像是Spring中的AoP对代码的增强。可以分为静态代理和动态代理。

可以看一个代理模式的通用写法:

  1. 定义一个接口,创建代理主题角色类
package zh.stu.proxy;

/**
 1. @Author:KoVaVo
 2. @Version:1.0.0
 3. @Description:
 */
public interface ICar {

    void run();
}
  1. 新建一个类并实现这个接口。真实角色主题类
package zh.stu.proxy;

/**
 1. @Author:KoVaVo
 2. @Version:1.0.0
 3. @Description:
 */
public class ProxyCar implements ICar {
    private ICar iCar;

    public ProxyCar(ICar iCar) {
        this.iCar = iCar;
    }

    public void run() {
        before();
        iCar.run();
        after();
    }

    public void before()
    {
        System.out.println("before......");
    }

    public void after(){
        System.out.println("after......");
    }
}
  1. 新建代理主题角色类
package zh.stu.proxy;

/**
 * @Author:KoVaVo
 * @Version:1.0.0
 * @Description:
 */
public class ProxyCar implements ICar {
    private ICar iCar;

    public ProxyCar(ICar iCar) {
        this.iCar = iCar;
    }

    public void run() {
        before();
        iCar.run();
        after();
    }

    public void before()
    {
        System.out.println("before......");
    }

    public void after(){
        System.out.println("after......");
    }
}

  1. List item测试调用代码
package zh.stu.proxy;

/**
 * @Author:KoVaVo
 * @Version:1.0.0
 * @Description:
 */
public class Main {
    public static void main(String[] args) {
        ProxyCar proxyCar = new ProxyCar(new HongQ());

        proxyCar.run();
    }
}

从静态代理到动态代理

静态代理的成本太高,采用动态代理的底层一般不需要我们直接去实现。升级操作,在以上原有的代码添加一个类如下:

package zh.stu.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Author:KoVaVo
 * @Version:1.0.0
 * @Description:
 */
public class JdkProxy implements InvocationHandler {

    private ICar target;

    public ICar getInstance(ICar target){
        this.target=target;
        Class<?> clazz = target.getClass();
        ClassLoader classLoader = clazz.getClassLoader();
        return (ICar) Proxy.newProxyInstance(classLoader,clazz.getInterfaces(),this);
//        this.target.getClass().
    }
    //重写实现接口的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object invoke = method.invoke(this.target, args);
        after();
        return invoke;
    }

    public void before(){
        System.out.println("签订买车合同");
    }

    public void after(){
        System.out.println("恭喜提车");
    }
}

测试:

package zh.stu.proxy;

/**
 1. @Author:KoVaVo
 2. @Version:1.0.0
 3. @Description:
 */
public class ProxyTest {
    public static void main(String[] args) {
        JdkProxy jdkProxy = new JdkProxy();

        ICar instance = jdkProxy.getInstance(new HongQ());
        instance.run();
    }
}

CGLIB和JDK的比较

  1. CGLiB执行代理方法对的效率之所以比JDK高,是因为CGlib采用了FastClass机制,为代理类和被代理类生成一个类,这个类会为代理类或被代理类的方法分配一个index(int)类型;这个index当作一个入参,这个时候FastClass就可以直接定位到被调用的方法直接调用,省去了反射调用,所以比jdk效率高。

  2. JDK 动态代理实现了被代理对象的接口,CLGlib代理继承了被代理的对象

  3. JDK动态代理和CGLIB代理都在运行时期生成字节码,JDK动态代理直接写class字节码,CGLib代理使用ASM框架课程Class字节码,CGLib代理实现比较复杂,生成代理类比JDK动态代理效率低。

  4. JDK动态代理调用代理方法是通过反射机制调用的,CGLib代理是通过FastClass机制直接调用方法的,CGLib代理的执行效率高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值