结构型模式-代理模式

一、代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

二、代理对象

package com.mo.structural.proxy.pojo;

/**
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 22:39
 */
public interface Moveable {
    /**
     * 抽象的方法,由实现类具体实现
     */
    void move();
}
package com.mo.structural.proxy.pojo;

import java.util.Random;

/**
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 22:40
 */
public class Car implements Moveable {

    @Override
    public void move() {
        // 实现开车
        try {
            Thread.sleep(new Random().nextInt(2000));
            System.out.println("汽车行驶中 ....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

二、静态代理

代理或被代理对象在代理之前是确定的。他们都实现了相同的接口或者继承相同的抽象类。

package com.mo.structural.proxy.steady.core;

import com.mo.structural.proxy.pojo.Car;

/**
 * 方式一
 * 继承实现代理
 *
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 22:43
 */
public class ExtendsProxyCar extends Car {

    @Override
    public void move() {
        long begin = System.currentTimeMillis();
        System.out.println("汽车开始行使 ...");
        super.move();
        long end = System.currentTimeMillis() - begin;
        System.out.println("汽车结束行使 ...,耗时: " + end);
    }
}
package com.mo.structural.proxy.steady.core;

import com.mo.structural.proxy.pojo.Moveable;

/**
 * 方式二
 * 聚合实现代理
 *
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 22:46
 */
public class GroupProxyCar implements Moveable {

    private Moveable moveable;

    public GroupProxyCar(Moveable moveable) {
        this.moveable = moveable;
    }

    @Override
    public void move() {
        long begin = System.currentTimeMillis();
        System.out.println("汽车开始行使 ...");
        moveable.move();
        long end = System.currentTimeMillis() - begin;
        System.out.println("汽车结束行使 ...,耗时: " + end);
    }
}
package com.mo.structural.proxy.steady.test;

import com.mo.structural.proxy.steady.core.ExtendsProxyCar;
import com.mo.structural.proxy.steady.core.GroupProxyCar;
import com.mo.structural.proxy.pojo.Car;
import org.junit.Test;

/**
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 22:49
 */
public class ProxyTest {

    /**
     * 继承代理测试
     */
    @Test
    public void extendsTest() {
        ExtendsProxyCar extendsProxyCar = new ExtendsProxyCar();
        extendsProxyCar.move();
    }

    /**
     * 聚合代理测试
     */
    @Test
    public void groupTest() {
        Car car = new Car();
        GroupProxyCar groupProxyCar = new GroupProxyCar(car);
        groupProxyCar.move();
    }

    /**
     * 说明:
     * 聚合代理相比继承代理更加灵活,能够将代理进行不同组合,实现不同的功能
     */
}

 

 三、动态代理

jdk代理

package com.mo.structural.proxy.dynamic.jdk;

import com.mo.structural.proxy.pojo.Car;
import com.mo.structural.proxy.pojo.Moveable;
import org.junit.Test;

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

/**
 * 方式一
 * jdk代理的步骤
 * 1. 实现InvocationHandler接口及具体业务
 * 2. 创建被代理的类以及接口
 * 3. 调用Proxy的静态方法,创建一个代理类
 * 4. 代理调用方法
 * <p>
 * jdk代理的说明
 * 只能代理实现接口的类
 *
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 23:14
 */
public class TimeHandler implements InvocationHandler {


    private Object object;

    public TimeHandler(Object object) {
        this.object = object;
    }

    /**
     * @param proxy  被代理的对象
     * @param method 被代理对象的方法
     * @param args   方法的参数
     * @return 方法的返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long begin = System.currentTimeMillis();
        System.out.println("汽车开始行使 ...");
        method.invoke(object, args);
        long end = System.currentTimeMillis() - begin;
        System.out.println("汽车结束行使 ...,耗时: " + end);
        return null;
    }


    @Test
    public void jdk() {
        Car car = new Car();
        Class<? extends Car> aClass = car.getClass();
        InvocationHandler handler = new TimeHandler(car);
        /**
         * ClassLoader loader 类加载器
         * Class<?>[] interfaces 实现的接口
         * InvocationHandler h
         */
        Moveable moveable = (Moveable) Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), handler);
        moveable.move();
    }
}

 

cglib代理

package com.mo.structural.proxy.dynamic.cglib;

/**
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 23:28
 */
public class People {

    public void move(){
        System.out.println("人在前进中 ...");
    }
}

 

package com.mo.structural.proxy.dynamic.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.junit.Test;

import java.lang.reflect.Method;

/**
 * cglib实现代理说明
 * 是通过继承的方式实现代理的,所以被final修改的类是不能被代理的
 * <p>
 * 依赖
 * <dependency>
 * <groupId>cglib</groupId>
 * <artifactId>cglib</artifactId>
 * <version>3.2.5</version>
 * </dependency>
 *
 * @author x.pan
 * @email px5215201314@163.com
 * @date 2020/7/12 23:29
 */
public class CglibProxy implements MethodInterceptor {


    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        // 设置创建子类的类
        enhancer.setSuperclass(clazz);
        // 设置回调
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 拦截所有目标类方法的调用
     *
     * @param o           目标类的实例
     * @param method      目标方法的放射对象
     * @param args        目标方法的反射参数
     * @param methodProxy 代理类的实例
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        long begin = System.currentTimeMillis();
        System.out.println("开始行使 ...");
        // 代理调用父类的方法
        methodProxy.invokeSuper(o, args);
        long end = System.currentTimeMillis() - begin;
        System.out.println("结束行使 ...,耗时: " + end);
        return null;
    }



    @Test
    public void cglib() {
        CglibProxy cglibProxy = new CglibProxy();
        People proxy = (People) cglibProxy.getProxy(People.class);
        proxy.move();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值