基于java的设计模式的代理模式

来源:互联网 发布:淘宝客服介入会怎么样 编辑:程序博客网 时间:2024/05/21 20:30

该文章是本人在学习慕课网中的代理模式的个人笔记

代理模式定义

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

常见的几种代理模式

远程代理:类似于客户端服务器这种模式,列一个为不同地理对象提供局域网代表对象虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建保护代理:控制对象的访问权限智能代理:提供对目标对象额外的服务

智能引用代理

静态代理动态代理

静态代理定义

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

package Proxy;


public interface Moveable {
public void move();
}


package Proxy;


import java.util.Random;


public class Car implements Moveable {


@Override
public void move() {


try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}


}
}


package Proxy.static_proxy;


import java.util.Random;


import Proxy.Car;


public class Car2 extends Car {

public void move() {
long startTime = System.currentTimeMillis();
System.out.println("汽车行驶中...");
super.move();
long endTime = System.currentTimeMillis();
System.out.println("汽车行驶结束");
System.out.println("汽车走得时间" + (endTime - startTime));
}
}

测试:

package Proxy;


import Proxy.static_proxy.Car2;


public class test1_static_extend_proxy {


public static void main(String[] args) {
Car car2 = new Car2();
car2.move();
}
}

测试结果:

汽车行驶中...
汽车行驶结束
汽车走得时间453

demo2使用聚合

package Proxy.static_proxy;


import Proxy.Car;


public class Car3{
private Car car;
public Car3(Car car){
this.car=car;
}
public void move(){
long startTime = System.currentTimeMillis();
System.out.println("汽车行驶中...");
car.move();
long endTime = System.currentTimeMillis();
System.out.println("汽车行驶结束");
System.out.println("汽车走得时间" + (endTime - startTime));
}
}

测试聚合方式:

package Proxy;


import Proxy.static_proxy.Car3;


public class test_staticc_juhe_proxy {
public static void main(String[] args) {
Car car = new Car();
Car3 car3 = new Car3(car);
car3.move();
}
}

测试结果

汽车行驶中...
汽车行驶结束
汽车走得时间847


使用继承方式来实现代理功能的叠加,代理类会无限的膨胀下去,所以这种方式不推荐使用。

使用聚合方式,通过代码演示

demo:

package Proxy.static_proxy;


import Proxy.Moveable;
/**
 * 时间代理
 * @author lailai
 *
 */
public class CarTimeProxy implements Moveable {


private Moveable m;


// 因为代理类和被代理类都是实现相同的接口,所以构造方法传递的对象也可以是Moveable对象
public CarTimeProxy(Moveable m) {
super();
this.m = m;
}


@Override
public void move() {
long startTime = System.currentTimeMillis();
System.out.println("汽车行驶中...");
m.move();
long endTime = System.currentTimeMillis();
System.out.println("汽车行驶结束");
System.out.println("汽车走得时间" + (endTime - startTime));


}


}


package Proxy.static_proxy;


import Proxy.Moveable;
/**
 * 日志代理
 * @author lailai
 *
 */
public class CarLogProxy implements Moveable {


private Moveable m;


// 因为代理类和被代理类都是实现相同的接口,所以构造方法传递的对象也可以是Moveable对象
public CarLogProxy(Moveable m) {
super();
this.m = m;
}


@Override
public void move() {
System.out.println("开始打印日志");
m.move();
System.out.println("日志打印结束" );
}


}


测试:

package Proxy;


import Proxy.static_proxy.CarLogProxy;
import Proxy.static_proxy.CarTimeProxy;


public class test2_manyProxy {
public static void main(String[] args) {
Car car = new Car();
System.out.println("----------创建time代理-------------");
CarTimeProxy timeCar = new CarTimeProxy(car);
timeCar.move();
System.out.println("----------创建log代理------------");
CarLogProxy logCar = new CarLogProxy(timeCar);
logCar.move();
System.out.println("-----------------------");
}
}

测试结果:

----------创建time代理-------------
汽车行驶中...
汽车行驶结束
汽车走得时间78
----------创建log代理------------
开始打印日志
汽车行驶中...
汽车行驶结束
汽车走得时间710
日志打印结束
-----------------------

以上是静态代理,下面是动态代理

分为JDK动态代理和使用cglib

jdk动态代理图:


(图片来自慕课网)

动态代理实现步骤

1.创建一个实现InvocationHandler接口的类,它必须实现invoke方法2.创建被代理的类以及接口3.调用Proxy的静态方法,创建一个代理类    newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)4.通过代理调用方法
demo:

package Proxy.Dynamic;


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


public class timeHandler implements InvocationHandler {
private Object target;


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


/**
* 在实际使用时,第一参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。 Object 方法的返回值
*/
@Override
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶...");
method.invoke(target);
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶...汽车行驶时间:" + (endtime - starttime) + "毫秒");
return null;
}


}

package Proxy.Dynamic;


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


import Proxy.Moveable;


public class loghandler implements InvocationHandler {


private Object Target;



public loghandler(Object target) {
super();
Target = target;
}


@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("-------startLog------");
method.invoke(Target);
System.out.println("-------endLog------");
return null;
}


}

测试:(一次代理与二次代理)

package Proxy.Dynamic;


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


public class timeHandler implements InvocationHandler {
private Object target;


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


/**
* 在实际使用时,第一参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。 Object 方法的返回值
*/
@Override
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶...");
method.invoke(target);
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶...汽车行驶时间:" + (endtime - starttime) + "毫秒");
return null;
}


}

测试结果:

----只有单独的时间代理----
汽车开始行驶...
汽车结束行驶...汽车行驶时间:302毫秒
----只有单独的时间代理----
在时间代理的基础上加上日志代理
-------startLog------
汽车开始行驶...
汽车结束行驶...汽车行驶时间:791毫秒
-------endLog------
--------结束---------



接下来使用cglib实现动态代理(下面对比来自慕课网)

JDK动态代理1.只能代理实现了接口的类2.没有实现接口的类不能实现JDK的动态代理CGLIB动态代理1.针对类来实现代理的2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用3.因为是使用继承的方式,所以不能对final修饰的类来进行代理
demo:

package Proxy.Dynamic_cglib;


import java.lang.reflect.Method;


import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


public class cglibTiemProxy implements MethodInterceptor {


private Enhancer enhance = new Enhancer();


@SuppressWarnings("rawtypes")
public Object getProxy(Class clazz) {
// 设置创建子类的类
enhance.setSuperclass(clazz);
enhance.setCallback(this);
return enhance.create();
}


@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("日志开始...");


// 代理类调用父类的方法
proxy.invokeSuper(obj, args);


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


}


package Proxy.Dynamic_cglib;


public class Train {
public void move() {
System.out.println("火车开动中");
}
}

测试:

package Proxy.Dynamic_cglib;


public class Client {
public static void main(String[] args) {
cglibTiemProxy proxy = new cglibTiemProxy();
Train train =(Train)proxy.getProxy(Train.class);//返回代理 
train.move();
}
}

测试结果:

日志开始...
火车开动中
日志结束...

这里有个必须要强调的是,jar包,如果不是maven项目,可能有依赖的jar包,例如这边依赖了一个asm.jar,不然会出现下面的错,

Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type

下面是我在某个项目中的直接拷贝的,刚好能用,试过随便添加吗,好像版本有差别(具体没验证)


代理模式-动态代理

在框架中典型的案例就是spring的aop(ioc是工厂模式)

原创粉丝点击