设计模式-代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。

一、静态代理

静态代理的代理类每次都需要手动创建。

代理类和真实类都需要实现接口。

接口类

/**
 * <p>
 *抽象主题角色
 * </p>
 *
 * @since 2022/3/21 17:19
 */
public interface TVCompany {
    TV produceTV();

    String print();
}

真实类

/**
 * <p>
 * 具体主题角色
 * </p>
 *
 * @since 2022/3/21 17:20
 */
public class TVFactory implements TVCompany {

    @Override
    public TV produceTV() {
        System.out.println("tvfactory prduce TV");
        return new TV("小米", "济南");
    }

    @Override
    public String print() {
        System.out.println("print TV");
        return "print TV";
    }
}

代理类

/**
 * <p>
 *代理主题角色 静态代理
 * </p>
 *
 * @since 2022/3/21 17:21
 */
public class TVProxy implements TVCompany {
    private TVCompany tvCompany;


    @Override
    public TV produceTV() {
        System.out.println("tvproxy prduce");
        if (ObjectUtil.isNull(tvCompany)) {
            tvCompany = new TVFactory();
        }
        return tvCompany.produceTV();
    }

    @Override
    public String print() {
        return "print TV";
    }
}

测试类

//静态代理
        TVProxy tvProxy = new TVProxy();
        TV tv = tvProxy.produceTV();
        System.out.println(tv.toString());

二、动态代理

从静态代理的代码中可以发现,静态代理的缺点显而易见,那就是当真实类的方法越来越多的时候,这样构建的代理类的代码量是非常大的,所以就引进动态代理.

动态代理允许使用一种方法的单个类(代理类)为具有任意数量方法的任意类(真实类)的多个方法调用提供服务,看到这句话,可以容易的联想到动态代理的实现与反射密不可分。
JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 java 语言的反射机制。

1.jdk动态代理

jdk动态代理工厂

/**
 * <p>
 * 代理主题角色 jdk动态代理
 * </p>
 *
 * @since 2022/3/21 17:26
 */
public class TVProxyFactory {
    private Object target;

    public TVProxyFactory(Object o) {
        this.target = o;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                                      target.getClass().getInterfaces(), (proxy, method, args) -> {
                                          System.out.println("tv proxy find factory for tv");
                                          Object invoke = method.invoke(target, args);
                                          return invoke;
                                      });
    }
}

测试代码

        //jdk 动态代理
        TVFactory tvCompany = new TVFactory();
        TVCompany tvCompany1 = (TVCompany) new TVProxyFactory(tvCompany).getProxy();
        System.out.println(tvCompany1.produceTV());
        System.out.println(tvCompany1.print());

1.静态代理中,代理类和真实类实现的是同一个接口,重写同样的方法;jdk动态代理中,代理类和真实类关系不大,代理类实现无侵入式的代码扩展。
2.静态代理中当接口中方法增加的时候,在代理类代码量也会增加,显然是不妥的;jdk动态代理解决了这个问题,当业务增加,代理类的代码不会增加。
3.jdk动态代理实现的是jdk自带InvocationHandler接口,实现了这个接口的类也叫拦截器类,也叫代理类。

2.cglib动态代理

从上面可以看出,jdk动态代理的前提条件是,要有接口存在,那还有许多场景是没有接口的,这个时候就需要cglib动态代理了,CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。

cgli代理类

/**
 * <p>
 * 代理主题角色 CGLIB动态代理
 * </p>
 *
 * @since 2022/3/21 17:37
 */
public class TVProxyCglib implements MethodInterceptor {


    public Object getProxyInstance(Class c) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(c);
        enhancer.setCallback(this);
        return enhancer.create();
    }


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("tvproxycglib enhancement");
        Object object = methodProxy.invokeSuper(o, objects);
        return object;
    }
}

测试代码

 // cglib 动态代理
        TVFactory tvFactoryS = (TVFactory) new TVProxyCglib().getProxyInstance(TVFactory.class);
        TVFactoryB tvFactoryB = (TVFactoryB) new TVProxyCglib().getProxyInstance(TVFactoryB.class);
        System.out.println(tvFactoryS.produceTV());
        System.out.println(tvFactoryS.print());
        System.out.println(tvFactoryB.produceTV());
        System.out.println(tvFactoryB.print());

glib动态代理和jdk动态代理的区别显而易见,但是实现逻辑差不多,cglib代理类是通过实现MethodInterceptor,重写intercept方法,通过生成被代理类的子类来达到代理增强代码的目的;而Jdk代理是通过实现InvocationHandler,重写invoke方法,通过生成接口的代理类来达到代码增强的目的,所以jdk动态代理的实现需要接口,cglib则不需要
 

文章参考出处:https://blog.csdn.net/weixin_43953283/article/details/125783249

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值