【设计模式】-代理模式

一 前言

java中的代理模式主流的有三种,分别是静态代理模式,cglib代理模式和java原生的代理模式;要学习cglib动态代理和java原生代理必须要掌握静态代理模式,地基是架起高楼大厦的基石;

二 静态代理模式

2.1 静态代理介绍

代理模式的定义是提供一个代理对象用来控制对这个对象的访问;我们以具体的例子说明静态代理模式:抽象类person中有个购物的方法,主体类zxzxz(知识追寻者)实现了person类,方法主体是想去澳洲购买大米,zxzxz在中国啊离澳洲很远,去一趟澳洲买东西成本太高了,不太现实。于是zxzxz在网上找了个去澳洲购物的代理(proxy)也实现了person的购物方法,帮zxzxz去澳洲买东西,然后zxzxz就可以用很低的代价获得澳洲的大米,本人还不用去澳洲,感觉很好对吧;

在这里插入图片描述

2.2 抽象类person

person接口中有一个抽象方法就是购物;

/**
 * @Author lsc
 * @Description <p> </p>
 * @Date 2019/11/20 17:00
 */
public interface Person {

    // 人的购买方法
    public String shop();
}

2.3 主体类zxzxz

主体类也就是代理的目标对象,其是被真正执行的主体;主体类实现了接口person,并重写了购物方法;

/**
 * @Author lsc
 * @Description <p> </p>
 * @Date 2019/11/20 17:02
 */
public class ZXZXZ implements Person {

    @Override
    public String shop() {
        return "去澳洲买大米";
    }

}

2.4 代理对象proxy

代理对象proxy也实现了person接口,但是其重写的购物方法的主体内容不是自己的,而是直接调用了主体类的购物方法;

/**
 * @Author lsc
 * @Description <p>代理对象 </p>
 * @Date 2019/11/20 17:03
 */
public class Proxy implements Person {

    // 知识追寻者
    private ZXZXZ zxzxz;
    // 代理的购买方法
    @Override
    public String shop() {
        // 对象为空则创建
        if (zxzxz==null){
            zxzxz =  new ZXZXZ();
        }
        // 调用知识追寻者的购买方法
        return zxzxz.shop();
    }
}

2.5 代理模式测试

  public static void main(String[] args) {
        // 创建代理对象
        Proxy proxy = new Proxy();
        // 调用代理对象的购买方法,实际上是zxzxz的购买方法
        String shop = proxy.shop();
        // 去澳洲买大米
        System.out.println(shop);
    }

三 jdk动态代理

3.1 jdk动态代理介绍

jdk动态代理对象主要通过 java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler 2个类实现动态代理;Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)有三个参数分别是

  1. ClassLoader(被代理对象的类加载器);
  2. interfaces 被代理对象的接口类型,即将被代理对象绑定到那些接口下;
  3. InvocationHandler(事件处理器)是 java.lang.reflect.InvocationHandler接口里面只有一个invoke(Object proxy, Method method, Object[] args)的抽象方法,我们需要重写invoke方法

3.1 抽象类person

/**
 * @Author lsc
 * @Description <p> </p>
 * @Date 2019/11/20 17:00
 */
public interface Person {

    // 人的购买方法
    public String shop();
}

3.2 目标对象ZXZXZ

/**
 * @Author lsc
 * @Description <p> </p>
 * @Date 2019/11/20 17:02
 */
public class ZXZXZ implements Person {

    @Override
    public String shop() {
        return "去澳洲买大米";
    }

}

3.3 动态代理对象

/**
 * @Author lsc
 * @Description <p> java生成的代理</p>
 * @Date 2019/11/20 20:01
 */
public class JProxy {

    // 被代理的对象
    private Object target;
    // 构造器 提供被代理的对象
    public JProxy(Object target){
        this.target = target;
    }

    // 进行动态代理

    public Object getProxyInstance(){
        // 1获得类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        // 2被代理对象的接口类型
        Class<?>[] interfaces = target.getClass().getInterfaces();
        // 3事件触发,将被代理的对象的方法做为参数传入
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 执行被代理对象的方法
                Object invoke = method.invoke(target, args);
                return invoke;
            }
        };
        // 获得代理对象
        Object instance = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return instance;
    }
}

3.3 jdk动态代理测试

    public static void main(String[] args) {
        // 创建被代理对象
        Person person = new ZXZXZ();
        // 创建代理对象
        JProxy jProxy = new JProxy(person);
        // 获得代理对象的实例
        Person proxyInstance = (Person)jProxy.getProxyInstance();
        // 调用代理对象的方法,实际上是被代理对象的方法
        String shop = proxyInstance.shop();
        // 去澳洲买大米
        System.out.println(shop);

    }


四 cglib动态代理

4.1 cglib动态代理介绍

cglib动态代理基于ASM的字节码生成库,允许在运行时形成代理,是一种子类代理;
cglib动态代理不像静态代理和jdk动态代理,其无需实现任何接口即可代理;cglib动态代理无法代理final修饰的类,其是外来物种,需要引入依赖;

 <dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.5</version>
        </dependency>
 </dependencies>

4.2 被代理对象

/**
 * @Author lsc
 * @Description <p> </p>
 * @Date 2019/11/20 17:02
 */
public class ZXZXZ {

   public String shop() {
        return "去澳洲买大米";
    }

}

4.3 代理对象

/**
 * @Author lsc
 * @Description <p>cglib动态代理 </p>
 * @Date 2019/11/20 21:57
 */
public class CglibProxy implements MethodInterceptor {

    // 被代理的对象
    private Object target;
    // 构造器 提供被代理的对象
    public CglibProxy(Object target){
        this.target = target;
    }

    public Object getCglibProxyInstance(){
        // 创建实例化工具
        Enhancer enhancer = new Enhancer();
        // 设置父类对象
        enhancer.setSuperclass(this.target.getClass());
        // 设置回调函数
        enhancer.setCallback(this);
        // 创建子类即被代理的对象
        return enhancer.create();
    }
    /*
     * @Author lsc
     * @Description <p> </p>
     * @Date  2019/11/20 22:03
     * @Param [被增强的对象, 要拦截的方法, 参数列表, 对方法进行代理]
     * @Return java.lang.Object
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 执行被代理对象的方法
        Object invoke = method.invoke(target, objects);
        return invoke;
    }

}

4.4 cglib动态代理测试

    public static void main(String[] args) {
        // 创建被代理对象
        ZXZXZ zxzxz = new ZXZXZ();
        // 创建代理对象
        CglibProxy cglibProxy = new CglibProxy(zxzxz);
        // 获得代理对象的实例
        ZXZXZ cglibProxyInstance = (ZXZXZ)cglibProxy.getCglibProxyInstance();
        // 调用代理对象的方法,实际上是被代理对象的方法
        String shop = cglibProxyInstance.shop();
        // 去澳洲买大米
        System.out.println(shop);
    }

五 支持作者

点赞加关注,谢谢;
在这里插入图片描述

发布了95 篇原创文章 · 获赞 106 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/youku1327/article/details/103173163