专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java代理模式详解(java的代理模式)

temp10 2024-10-24 17:22:00 java教程 10 ℃ 0 评论

一、什么是代理模式

代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是代理类与委托类有同样的接口。代理模式是常用的java设计模式。

Java代理模式详解(java的代理模式)

代理模式能够在不修改源码的情况下增强方法,在方法前后增加日志记录,权限管理等功能。

表现形式如图:

在Java中,代理模式分成2种:静态代理模式和动态代理模式;

静态代理的模式在平时生活中也很常见,比如买火车票这件小事,黄牛相当于是火车站的代理,我们可以通过黄牛或者代售点进行买票行为,但只能去火车站进行改签和退票,因为只有火车站才有改签和退票的方法。

动态代理中,代理类并不是在Java代码中实现,而是在运行时期生成,相比静态代理,动态代理可以很方便的对委托类的方法进行统一处理,如添加方法调用次数、添加日志功能等等,动态代理分为jdk动态代理和cglib动态代理,下面通过一个例子看看如何实现jdk动态代理。

二、代理模式的优缺点

优点:

职责清晰。

高扩展性。

智能化。

缺点:

由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。

实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

其他模式对比

和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。

和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

三、使用场景

代理模式主要解决在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

1.应用场景

按职责来划分,通常有以下使用场景:

远程代理。

虚拟代理。

Copy-on-Write 代理。

保护(Protect or Access)代理。

Cache 代理。

防火墙(Firewall)代理。

同步化(Synchronization)代理。

智能引用(Smart Reference)代理。

2.应用实例

Windows 桌面以及资源管理器里面的快捷方式。

买火车票不一定在火车站买,也可以去代售点,也可以网购。

Spring AOP 中 用到的动态代理。

四、代码实现

1. 静态代理模式

静态代理满足如下的几个条件:

代理对象的类是真实存在的,并非动态生成的。

代理对象持有被代理对象的引用。

代理对象中的方法通过被代理对象的引用调用被代理对象的方法,同时执行代理逻辑。

下面是一个简单的代理模式:

接口类:

/*

* 接口

* 代理类和委托类都必须实现该类

*/

public interface ISubject {

//处理任务的抽象方法

public void dealTask(String task);

}

委托类:

/*

* 真实角色(被代理类,委托类)

* 实现接口Isubject

*/

public class RealSubject implements ISubject {

@Override

public void dealTask(String task) {

//真实角色处理任务

System.out.println("正在"+task);

}

}

代理类:

/*

* 代理类

* 实现ISubject接口

* 持有被代理类的引用

*/

public class Proxy implements ISubject {

//持有被代理类的引用

private RealSubject realSubject;

//在构造方法中初始化被代理类

public Proxy(RealSubject r) {

this.realSubject=r;

}

@Override

//在该方法中加入代理逻辑

public void dealTask(String task) {

System.out.println("开始帮忙....");

//加入线程睡眠模拟帮忙的行为

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//真正执行动作的仍然是真实角色

realSubject.dealTask(task);

}

}

静态工厂类:

/*

* 静态工厂类

* 对于客户端来说 并不关心执行动作的是代理对象还是真实角色

* 所以我们创建一个静态方法直接返回对象

*/

public class StaticFactory {

//调用此方法获得实例

public static ISubject getInstance(){

return new Proxy(new RealSubject());

}

}

测试类:

/*

* 测试类(客户类)

*/

public class Test {

public static void main(String[] args) {

//创建代理对象时需要一个真实对象的实例

ISubject instance = StaticFactory.getInstance();

//使用代理类的方法

instance.dealTask("敲代码");

}

}

真正的业务功能还是有委托类来实现,但是在实现业务类之前的一些公共服务。例如在项目开发中我们没有加入缓冲,日志这些功能,后期想加入,我们就可以使用代理来实现,而没有必要打开已经封装好的委托类。

2.动态代理模式

1、定义业务逻辑

public interface Service {

//目标方法

public abstract void add();

}

public class UserServiceImpl implements Service {

public void add() {

System.out.println("This is add service");

}

}

2、利用 java.lang.reflect.Proxy类和 java.lang.reflect.InvocationHandler接口定义代理类的实现。

class MyInvocatioHandler implements InvocationHandler {

private Object target;

public MyInvocatioHandler(Object target) {

this.target = target;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("-----before-----");

Object result = method.invoke(target, args);

System.out.println("-----end-----");

return result;

}

// 生成代理对象

public Object getProxy() {

ClassLoader loader = Thread.currentThread().getContextClassLoader();

Class<?>[] interfaces = target.getClass().getInterfaces();

return Proxy.newProxyInstance(loader, interfaces, this);

}

}

3、使用动态代理

public class ProxyTest {

public static void main(String[] args) {

Service service = new UserServiceImpl();

MyInvocatioHandler handler = new MyInvocatioHandler(service);

Service serviceProxy = (Service)handler.getProxy();

serviceProxy.add();

}

}

执行结果:

-----before-----

This is add service

-----end-----

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表