Uninote
Uninote

定义

  • 为其他对象提供一种代理以控制对这个对象的访问
  • 代理对象起到中介服务,可以去掉和新增服务

静态代理

  • 代理和被代理的对象在代理之前是确定的,他们都实现相同的接口或继承相同的类
/**
 * 定义汽车行驶接口
 */
public interface Moveable {
    void move();
}
/**
 * 定义汽车实现接口
 */
public class Car implements Moveable {
    @Override
    public void move() {

        try {
            //模拟汽车行驶
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("行驶中...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
继承方式实现代理
/**
 * 继承方式实现代理
 */
public class CarExtends extends Car {

    @Override
    public void move() {
        long start = System.currentTimeMillis();
        System.out.println("开始行驶...");
        //实现对car的代理
        super.move();
        System.out.println("结束行驶...");
        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end - start));
    }

    public static void main(String[] args) {
        Moveable m = new CarExtends();
        m.move();
    }
}

运行结果:
开始行驶...
行驶中...
结束行驶...
用时:154
聚合方式实现代理(推荐)
/**
 * 聚合方式实现代理
 */
public class CarTimeProxy implements Moveable {
    private Moveable m;

    public CarTimeProxy(Moveable m) {
        this.m = m;
    }

    @Override
    public void move() {
        long start = System.currentTimeMillis();
        System.out.println("开始行驶...");
        //实现对car的代理
        m.move();
        System.out.println("结束行驶...");
        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end - start));
    }

    public static void main(String[] args) {
        Moveable m = new CarTimeProxy(new Car());
        m.move();
    }
}

运行结果:
开始行驶...
行驶中...
结束行驶...
用时:856
代理功能的叠加
/**
 * 日志代理
 * 模拟日志和时间 功能的叠加
 */
public class CarLogProxy implements Moveable {
    private Moveable m;

    public CarLogProxy(Moveable m) {
        this.m = m;
    }

    @Override
    public void move() {
        System.out.println("日志开始...");
        //实现对car的代理
        m.move();
        System.out.println("日志结束...");
    }

    public static void main(String[] args) {
        Car car = new Car();
        //先记录时间在记录日志
        System.out.println("==================先记录时间再记录日志====================");
        CarLogProxy carLogProxy = new CarLogProxy(car);
        CarTimeProxy carTimeProxy = new CarTimeProxy(carLogProxy);
        carTimeProxy.move();

        System.out.println("==================先记录日志再记录时间====================");
        CarTimeProxy carTimeProxy1 = new CarTimeProxy(car);
        CarLogProxy carLogProxy1 = new CarLogProxy(carTimeProxy1);
        carLogProxy1.move();
    }
}
//注意:如果用继承方式,这里实现两种情况就需要两个类来继承car,显然不方便
//这里只是汽车,如果现在有火车自行车也许要时间和日志功能,怎么办,使用动态代理

动态代理

JDK动态代理

  • 如图所示,动态代理就是在代理类(ProxySubject)和被代理类(RealSubject)之间加了一个的事务处理器(InvocationHandler)
  • InvocationHandler位于java.lang.reflect
/**
 *
 * @param proxy 代理类
 * @param method 被代理方法
 * @param args 方法参数
 * @return 被代理方法返回值
 * @throws Throwable
 */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
  • Proxy:动态代理类
/**
 * @param loader 被代理类的类加载器
 * @param interfaces 被代理类的实现接口
 * @param h InvocationHandler
 * @return 返回代理类的一个实例
 * @throws IllegalArgumentException
 */
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
jdk动态代理实现
import com.interview.proxy.Car;
import com.interview.proxy.Moveable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TimeHandler implements InvocationHandler {

    private Object target;

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

    /**
     * @param proxy 被代理对象
     * @param method 被代理对象方法
     * @param args 方法参数
     * @return 被代理方法返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        System.out.println("开始行驶...");
        //有参数和返回值时
        //        Object obj = method.invoke(target, args);
        method.invoke(target);
        System.out.println("结束行驶...");
        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end - start));
        return null;
    }

    public static void main(String[] args) {
        Car car = new Car();
        InvocationHandler h = new TimeHandler(car);
        Class<?> clazz = car.getClass();
        ClassLoader c = clazz.getClassLoader();

        Moveable m = (Moveable) Proxy.newProxyInstance(c, clazz.getInterfaces(), h);
        m.move();
    }
}

cglib动态代理

引入jar包

public class Train {

    public void move(){
        System.out.println("火车行驶中...");
    }
}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    /**
     * 获取代理类
     * @param clazz
     * @return
     */
    public Object getProxy(Class clazz) {
        //设置创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 拦截所有目标类方法的调用
     * @param o 目标类实例
     * @param method 目标方法反射对象
     * @param objects 方法参数
     * @param methodProxy 代理类实例
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("日志开始...");
        //代理类调用父类的方法
        Object obj = methodProxy.invokeSuper(o, objects);
        System.out.println("日志结束...");
        return obj;
    }

    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        Train train = (Train) cglibProxy.getProxy(Train.class);
        train.move();
    }
}

JDK动态代理和cglib动态代理区别

  • JDK动态代理只能代理实现了接口的类
  • cglib动态代理针对类来实现,对制定目标产生一个子类,通过方法拦截技术拦截所有的父类方法的调用

mybatis-generator自动生成代码

设计模式-单例模式

点赞(0) 阅读(223) 举报
目录
标题