• 代理模式


    引用:https://www.cnblogs.com/daniels/p/8242592.html

    定义:

    代理是一种设计模式,是指通过代理对象来访问目标对象,通俗的来讲就像我们生活中的中介、经纪人。

    作用:

    中介隔离作用:客户类不想或无法直接访问目标类,可使用代理类作为客户类与目标类之间的中介

    开闭原则:代理类除了作为客户类与目标类之间的中介,还可以在代理类中增加额外功能来扩展目标类的功能,

    一、静态代理:

    静态代理指的是,由程序员创建或特定工具自动生成源代码,再对其进行编译。在程序运行前,代理类的.class文件就已经存在了。

    代理三要素:接口、接口实现类,接口代理类

    接口:
    public interface BuyHouse {
        public void buyHouse();
    }
    实现类:
    public class BuyHouseImpl implements BuyHouse {
    
        public void buyHouse() {
            System.out.println("买房");
        }
    }
    静态代理类:
    public class StaticProxy implements BuyHouse {
        private BuyHouse buyHouse;
    
        public StaticProxy(final BuyHouse buyHouse) {
            this.buyHouse = buyHouse;
        }
    
        public void buyHouse() {
            System.out.println("买房前准备");
            buyHouse.buyHouse();
            System.out.println("买房后装修");
        }
    }
    测试类:
    public class StaticProxyTest {
        @Test
        public void buyHouse(){
            BuyHouse buyHouse = new BuyHouseImpl();
            StaticProxy buyHouseProxy = new StaticProxy(buyHouse);
            buyHouseProxy.buyHouse();
        }
    }
    结果:
    买房前准备
    买房
    买房后装修

    静态代理总结:

    优点:在符合开闭原则的情况下对目标对象进行功能扩展。

            缺点:需为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。

    二、JDK动态代理

    在动态代理中我们不需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK在运行时动态的来创建。

    动态代理类:
    public class DynamicProxyHandler implements InvocationHandler {
        private Object object;
    
        public DynamicProxyHandler(final Object object) {
            this.object = object;
        }
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("买房前准备");
            Object result = method.invoke(object, args);
            System.out.println("买房后装修");
            return result;
        }
    }
    测试类:
    public class DynamicProxyHandlerTest {
        @Test
        public void buyHouse() {
            BuyHouse buyHouse = new BuyHouseImpl();
            BuyHouse buyHouseProxy = (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader(), new Class[]{BuyHouse.class}, new DynamicProxyHandler(buyHouse));
            buyHouseProxy.buyHouse();
        }
    }
    结果:
    买房前准备
    买房
    买房后装修

    注意Proxy.newProxyInstance()法接受三个参数:

    • ClassLoader loader:指定当前目标对象使用的类加载器
    • Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
    • InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

    jdk动态代理总结:
    代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理

    三、CGLib动态代理

    cglib通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用

    动态代理类:
    public class CglibProxy implements MethodInterceptor {
        private Object target;
    
        public Object getInstance(final Object target) {
            this.target = target;
            Enhancer enhancer = new Enhancer();
    //设置为父类 enhancer.setSuperclass(
    this.target.getClass());
    //设置回调函数 enhancer.setCallback(
    this);
    //创建之类
    return enhancer.create(); } public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("买房前准备");
    //执行目标对象的方法 Object result
    = method.invoke(target, args); System.out.println("买房后装修"); return result; } } 测试类: public class CglibProxyTest { @Test public void buyHouse() { BuyHouse buyHouse = new BuyHouseImpl(); CglibProxy cglibProxy = new CglibProxy(); BuyHouse buyHouseProxy = (BuyHouseImpl) cglibProxy.getInstance(buyHouse); buyHouseProxy.buyHouse(); } } 结果: 买房前准备 买房 买房后装修

    CGLib动态代理总结:

    CGLib由于是采用动态创建子类的方法,对于final修饰的方法无法进行代理。

  • 相关阅读:
    线段树节点到底开多大
    HDU4901 The Romantic Hero DP
    VIM 配置文件可执行命令
    codeforces159D
    codeforces416B
    codeforces165C
    codeforces332B
    Node.js权威指南 (9)
    iOS-android-windowsphone等移动终端平台开发流程图
    前端面试题细节问题
  • 原文地址:https://www.cnblogs.com/tilamisu007/p/9392284.html
Copyright © 2020-2023  润新知