详解JAVA设计模式之代理模式

网友投稿 240 2022-12-04


详解JAVA设计模式之代理模式

什么是设计模式(Design Pattern)?

设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。

代理模式的定义?

代理模式就是为其他对象提供一种代理,以控制对这个对象的访问。

代理对象起到中介作用,可去掉功能服务或增加额外的服务。

代理对象和目标对象的关系?

代理对象:增强后的对象

目标对象:被增强的对象

他们不是绝对的,会根据情况发生变化。

代理模式的两种实现方式?

1.静态代理:代理和被代理对象在代理之前是确定的,它们都实现相同的接口或者继承相同的抽象类。

2.动态代理:JDK通过接口反射得到字节码,然后把字节码转换成class(通过native方法)

静态代理实现的两种方式?

使用继承方式实现和使用聚合方式实现。

继承:代理对象继承目标对象,重写需要增强的方法。缺点:代理类过多,产生类爆炸。

聚合:目标对象和代理对象实现同一个接口,代理对象当中要包含目标对象。

动态代理的实现方式?

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):返回代理类的一个实例,返回后的代理类可以当做被代理类使用(可使用被代理类在接口中声明过的方法)

所谓的动态代理是这样一种class:它是在运行时生成的class,该class需要实现一组interface,使用动态代理类时,必须实现InvocationHandler接口。

JDK动态代理和CGLIB动态代理的区别?

1.JDK动态代理只能代理实现了接口的类,没有实现接口的类不能实现JDK的动态代理。

2.CGLIB动态代理针对类来实现代理的,对指定目标类产生一个子类,通过方法拦截技术拦截所有的父类方法的调用。

动态代理实现的思路:

1.声明一段源码(动态产生代理)

2.编译源码(JDK Compiler API ),产生新的类(代理类)

3.将这个类load到内存中,产生一个新的对象(代理对象)

4.return 代理对象。

使用静态代理的例子:

1.首先创建业务逻辑接口

/**

* 接口

* @author Administrator

*

*/

public interface Moveable {

/**

*

* 接口中的方法

* @Description: TODO

* @returnType: void

*/

void move();

}

2.创建实现类,实现接口中的方法

/**

* 实现类

* @author Administrator

*

*/

public class Car implements Moveable {

@Override

public void move() {

//实现开车

try {

Thread.sleep(new Random().nextInt(1000));

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

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

3.使用继承方式实现对实现类的代理

/**

* 使用继承方式实现代理

* @author Administrator

*

*/

public class Car2 extends Car {

/* (non-Javadoc)

* @see com.wk.design.proxy.Car#move()

* 直接调用父类的move方法,这样就形成了一个Car2对Car的代理

*/

@Override

public void move() {

long startTime = System.currentTimeMillis();

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

//使用继承的方式调用父类的move()方法

super.move();

long endTime = System.currentTimeMillis();

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

}

}

4.创建测试类

/**

* 测试类

* @author Administrator

*

*/

public class Test {

public static void main(String[] args) {

// Car car = new Car();

// car.move();

//使用继承方式实现代理

Moveable car2 = new Car2();

car2.move();

//使用聚合方式实现代理

// Car car = new Car();

// Moveable car3 = new Car3(car);

// car3.move();

}

}

5.使用聚合方式实现对实现类的代理

日志代理类

/**

*

* 日志代理类

* @author Administrator

*

*/

public class CarLogProxy implements Moveable {

/**

* 使用接口声明代理类

*/

private Moveable m;

/**

* 通过构造方法的参数传入代理类

* @param m

*/

public CarLogProxy(Moveable m) {

super();

this.m = m;

}

@Override

public void move() {

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

//调用代理类的方法

m.move();

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

}

}

时间代理类

/**

* 时间代理类

* @author Administrator

*

*/

public class CarTimeProxy implements Moveable {

/**

* 使用接口声明代理类

*/

private Moveable m;

/**

* 通过构造方法的参数传入代理类

* @param m

*/

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("汽车行驶结束... 汽车行驶时间:"+(endTime-startTime)+"毫秒。");

}

}

6.创建聚合方式测试类

/**

* 聚合代理测试类

* @author Administrator

*

*/

public class TestJuHeProxy {

public static void main(String[] args) {

Car car = new Car();

//先记录日志,再记录时间

// CarTimeProxy ctp = new CarTimeProxy(car);

// CarLogProxy clp = new CarLogProxy(ctp);

// clp.move();

//先记录时间,再记录日志

CarLogProxy clp = new CarLogProxy(car);

CarTimeProxy ctp = new CarTimeProxy(clp);

ctp.move();

}

}

使用JDK动态代理实现的例子:

1.创建一个实现接口InvocationHandler的类,它必须实现invoke()方法。

2.创建被代理类及接口

3.调用Proxy的静态方法,创建一个代理类

4.通过代理调用方法

/**

* 使用jdk的动态代理

* @author Administrator

*

*/

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 {

//在执行被代理对象的方法之前执行自己的逻辑

long startTime = System.currentTimeMillis();

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

//执行被代理对象的方法

method.invoke(target);

//在执行被代理对象的方法之后执行自己的逻辑

long endTime = System.currentTimeMillis();

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

return null;

}

}

/**

* JDK动态代理测试类

* @author Administrator

*

*/

public class JdkProxyTest {

public static void main(String[] args) {

Car car = new Car();

InvocationHandler h = new TimeHandler(car);

Class> cls = car.getClass();

/**

* 参数:

* loader : 类加载器

* interfaces : 实现接口

* h InvocationHandler

*/

Moveable m= (Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);

//执行被代理类的方法

m.move();

}

}

使用CGLIB动态代理实现的例子:

1.创建代理类,实现MethodInterceptor接口

2.使用Enhancer类创建代理方法

3.创建被代理类,并编写代理方法

4.通过代理调用方法

/**

* 使用cglib动态代理

* @author Administrator

*

*/

public class Train {

public void move(){

System.out.println("火车行驶中。。。");

}

}

public class CglibProxy implements MethodInterceptor {

private Enhancer enhancer = new Enhancer();

//创建代理类方法

public Object getProxy(Class clazz){

//设置创建子类的类

enhancer.setSuperclass(clazz);

//回调函数

enhancer.setCallback(this);

//创建并返回子类的实例

return enhancer.create();

}

/**

* 作用:拦截所有目标类方法的调用

* obj : 目标类的实例

* m : 目标方法的反射对象

* args : 方法的参数

* proxy : 代理类的实例

*/

@Override

public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {

//在调用方法时实现自己的业务逻辑

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

//代理类调用父类的方法

proxy.invokeSuper(obj, args);

//调用方法之后实现自己的业务逻辑

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

return null;

}

}

/**

* 使用cglib动态代理的测试类

* @author Administrator

*

*/

public class CglibProxyTest {

public static void main(String[] args) {

CglibProxy proxy = new CglibProxy();

//传入要代理的类

Train t = (Train)proxy.getProxy(Train.class);

//执行方法

t.move();

}

}

以上就是详解JAVA设计模式之代理模式的详细内容,更多关于JAVA 代理模式的资料请关注我们其它相关文章!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:深入分析JAVA Synchronized关键字
下一篇:JAVA 区分集合和数组
相关文章

 发表评论

暂时没有评论,来抢沙发吧~