代理模式

为其他对象提供一种代理以控制对这个对象的访问。
代理对象起到中介作用,可去掉功能服务或增加额外的服务。

远程代理:为不同地理的对象提供局域网代表对象。eg.分店和总店的管理
虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建。eg.浏览网站时图片加载
保护代理:控制对一个对象的访问的权限。eg.网站各用户的权限
智能引用代理:提供对目标对象额外的服。eg.火车站和其代售点

静态代理:继承方式,聚合方式
动态代理:JDK动态代理,CGLIB动态代理

静态代理:代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类。
这里写图片描述
eg:模拟汽车行驶
普通方式实现汽车行驶

public interface MoveAble {

    public void move();

}
public class Car implements MoveAble{

    @Override
    public void move() {

        System.out.println("汽车开始行驶...");

        long starttime=System.currentTimeMillis();

        try {
            System.out.println("汽车行驶中...");
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        long endtime=System.currentTimeMillis();

        System.out.println("汽车结束行驶...  行驶时间: "+(endtime-starttime)+" 毫秒");

    }

}
@Test
public void TestCarMove(){

    Car car=new Car();
    car.move();

}

结果:

汽车开始行驶...
汽车行驶中...
汽车结束行驶...  行驶时间: 5 毫秒

下面将通过继承和聚合两种方式来实现静态代理
更改Car类,去除时间管理

public class Car implements MoveAble{

    @Override
    public void move() {

        try {
            System.out.println("汽车行驶中...");
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

通过继承方式来实现静态代理

public class Car2 extends Car {

    @Override
    public void move() {

        System.out.println("汽车开始行驶...");

        long starttime = System.currentTimeMillis();

        super.move();

        long endtime = System.currentTimeMillis();

        System.out.println("汽车结束行驶...  行驶时间: " + (endtime - starttime) + " 毫秒");
    }

}
@Test
public void TestCarMove2(){

    MoveAble ma=new Car2();
    ma.move();

}

结果:

汽车开始行驶...
汽车行驶中...
汽车结束行驶...  行驶时间: 34 毫秒

使用聚合的方式来实现静态代理

public class Car3 implements MoveAble {

    private Car car;

    public Car3(Car car) {
        super();
        this.car = car;
    }

    @Override
    public void move() {
        // TODO Auto-generated method stub

        System.out.println("汽车开始行驶...");

        long starttime = System.currentTimeMillis();

        car.move();

        long endtime = System.currentTimeMillis();

        System.out.println("汽车结束行驶...  行驶时间: " + (endtime - starttime) + " 毫秒");

    }

}
@Test
public void TestCarMove3(){

    Car c=new Car();
    MoveAble ma=new Car3(c);
    ma.move();

}

结果:

汽车开始行驶...
汽车行驶中...
汽车结束行驶...  行驶时间: 564 毫秒

聚合比继承更适合代理,进行功能叠加更方便
eg:汽车形式增加时间管理和日志管理

public class CarTimeProxy implements MoveAble{

    private MoveAble ma;

    public CarTimeProxy(MoveAble ma) {
        super();
        this.ma = ma;
    }

    @Override
    public void move() {

        System.out.println("汽车开始行驶...");

        long starttime = System.currentTimeMillis();

        ma.move();

        long endtime = System.currentTimeMillis();

        System.out.println("汽车结束行驶...  行驶时间: " + (endtime - starttime) + " 毫秒");

    }

}
public class CarLogProxy implements MoveAble{

    private MoveAble ma;

    public CarLogProxy(MoveAble ma) {
        super();
        this.ma = ma;
    }

    @Override
    public void move() {

        System.out.println("日志开始...");

        ma.move();

        System.out.println("日志结束...");

    }

}
@Test
public void TestCarMove4(){

    Car car=new Car();
    CarTimeProxy ctp=new CarTimeProxy(car);
    CarLogProxy clp=new CarLogProxy(ctp);
    clp.move();

}

结果:也可更改组合顺序,先进行日志管理再进行时间管理

日志开始...
汽车开始行驶...
汽车行驶中...
汽车结束行驶...  行驶时间: 991 毫秒
日志结束...

动态代理
这里写图片描述

JDK动态代理:只能对实现了接口的类实现代理,没有接口就不能实现JDK动态代理
1. 目的:动态产生代理,实现对不同类、不同方法的代理
2. 运行时生成的class,该class需要实现一组interface,产生的代理类并不能做什么事情,必须实现InvocationHandler接口来接管实际的工作。想实现的功能是在handler中去实现的
3. java动态代理类,位于java.lang.reflect包下,一般涉及两个类:
(1)Interface InvocationHandler:该接口中仅定义了一个方法public object invoke(Object obj,Method method,Object[] args):实际使用中,obj指被代理类的对象,method指被代理的方法,args为该方法参数数组。这个抽象方法在代理类中动态实现。实现该接口即为代理的事务处理器。
(2)Proxy:该类即为动态代理类:
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以被当作代理类使用,可使用被代理类的在接口中声明过的方法。第一个参数loader为被代理类的加载器,通过被代理类.getClass().getClassLoader()得到、第二个参数interfaces为被代理类实现的所有接口,同样通过getClass().getInterfaces()得到、 第三个参数handler就是自己实现的InvocationHandler的实现类的对象
这里写图片描述
4.动态代理实现:
(1)声明一个代理h实现InvocationHandler接口,通过构造方法接受被代理类,并实现invoke方法,添加业务逻辑(实现原有功能并添加额外功能)
(2)在测试类中,通过共同实现接口的实例获得代理对象,并实现方法,如Interface1 i = (Interface1)Proxy.newProxyInstance(classLoader,classInterfaces,h);
(3)通过动态代理对象i,代用其方法i.fun();

eg:

public class TimeHandler implements InvocationHandler {

    private Object target;

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

    /*
     * 参数:
     * proxy  被代理对象
     * method  被代理对象的方法
     * args 方法的参数
     * 
     * 返回值:
     * Object  方法的返回值
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub

        System.out.println("汽车开始行驶...");

        long starttime = System.currentTimeMillis();

        method.invoke(target);

        long endtime = System.currentTimeMillis();

        System.out.println("汽车结束行驶...  行驶时间: " + (endtime - starttime) + " 毫秒");

        return null;
    }

}
@Test
public void TestCarMove(){

    Car car=new Car();

    TimeHandler handler=new TimeHandler(car);
    Class<?> c=car.getClass();
    /**
     * loader  类加载器
     * interfaces  实现接口
     * h InvocationHandler
     */
    MoveAble ma=(MoveAble)Proxy.newProxyInstance(c.getClassLoader(), c.getInterfaces(), handler);

    ma.move();

}

结果:

汽车开始行驶...
汽车行驶中...
汽车结束行驶...  行驶时间: 785 毫秒

在原有基础上增加日志管理

public class TimeHandler implements InvocationHandler {

    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub

        System.out.println("汽车开始行驶...");

        long starttime = System.currentTimeMillis();

        method.invoke(target);

        long endtime = System.currentTimeMillis();

        System.out.println("汽车结束行驶...  行驶时间: " + (endtime - starttime) + " 毫秒");

        return null;
    }

}
@Test
public void TestCarMove2(){

    Car car=new Car();

    LogHandler log=new LogHandler(car);
    Class<?> cls=car.getClass();
    MoveAble logma=(MoveAble)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), log);

    TimeHandler time=new TimeHandler(logma);
    Class<?> logcls=logma.getClass();
    MoveAble timema=(MoveAble)Proxy.newProxyInstance(logcls.getClassLoader(), logcls.getInterfaces(), time);

    timema.move();

}

结果:

汽车开始行驶...
日志开始...
汽车行驶中...
日志结束...
汽车结束行驶...  行驶时间: 164 毫秒

Cglib代理:针对类来实现代理的,针对飙指定目标类产生一个子类,通过方法拦截技术拦截所有的父类方法的调用。
1. cblib是通过继承实现,所以final修饰的类不能被代理
2. CglibProxy要实现MethodInterceptor

eg:

public class Train {

    public void move(){
        System.out.println("火车行驶中...");
    }

}
public class TimeCglib implements MethodInterceptor{

    private Object target;

    //两种构造方式,其intercept方法中对应不同的invoke方法

    public Object getProxy(Class<?> cls){

        //设置创建子类的类
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(cls);
        enhancer.setCallback(this);

        return enhancer.create();
    }

    public Object getProxy(Object target){

        this.target=target;

        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);

        return enhancer.create();

    }

    /**
     * 拦截所有目标类方法的调用
     * object   目标类的实例
     * method   目标方法的反射对象
     * objects  方法的参数
     * methodProxy  代理类的实例
     */
    @Override
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println("火车开始行驶...");

        long starttime = System.currentTimeMillis();

        //两种方式
        //代理类调用父类的方法
        methodProxy.invokeSuper(object, objects);
        //目标对象调用其方法,需要传入目标对象target
//      method.invoke(target);

        long endtime = System.currentTimeMillis();

        System.out.println("火车结束行驶...  行驶时间: " + (endtime - starttime) + " 毫秒");

        return null;
    }

}
@Test
public void TestTrainMove(){

    TimeCglib time=new TimeCglib();
    Train train=(Train)time.getProxy(Train.class);//传入的参数是类
    train.move();

}

@Test
public void TestTrainMove2(){

    Train train=new Train();

    TimeCglib time=new TimeCglib();
    Train t=(Train)time.getProxy(train);//传入的参数是对象

    t.move();

}

结果:

火车开始行驶...
火车行驶中...
火车结束行驶...  行驶时间: 0 毫秒
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值