Java实现代理模式

1.代理模式概念


**代理模式(Proxy Pattern)**是一种结构型设计模式,属于GOF23种设计模式之一。它通过某种代理来控制对目标对象的访问,扩展目标对象的功能,甚至可以替换目标对象。它的应用相当广泛,许多框架都使用了代理模式来实现各种中间件功能。

代理模式使用场景:

  1. 远程代理:为一个对象在不同的地址空间提供局部代表,此代表会将客户端的请求转发给真实的对象,并返回真实对象的响应数据。这是代理模式的典型应用,例如Dubbo RPC框架。
  2. 缓存代理:为一个对象提供缓存,以缓解目标对象的压力。例如Ehcache框架。
  3. 懒加载:为一个对象提供懒加载,只在真正需要对象时创建它。例如Hibernate的sessionFactory。
  4. 日志记录:在访问一个对象时记录日志或其他与之相关的事件。例如Spring AOP。
  5. 智能代理:为一个对象提供额外的行为,如统计功能或异常处理。例如Dubbo框架对服务提供者进行统计和监控。

总结来说,代理模式常用于以下目的:

  • 控制目标对象的访问
  • 延迟目标对象的创建(懒加载)
  • 为目标对象提供中间件服务(远程调用、缓存、日志等)
  • 对目标对象进行装饰以提供附加功能(监控统计、安全校验等)

2.代理模式实现方式


2.1 静态代理

静态代理:代理类和目标对象的类都是在编译期确定的。代理类包含目标对象的实例,并在同一时刻只能为一个目标对象提供服务。实现简单,但是会产生很多代理类。
在这里插入图片描述
图中的 Hello是程序中的业务逻辑接口,HelloImpl是实现了 Hello接口的真正业务类,Proxy 是实现了 Hello接口的代理类,封装了一个 HelloImpl引用。在程序中不会直接调用 HelloImpl对象的方法,而是使用 Proxy 对象实现相关功能。

public interface Hello {
    void sayHello();
}

public class HelloImpl implements Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello World!");
    } 
}

public class Proxy implements Hello {
    private Hello hello;
    
    public Proxy(Hello hello) {
        this.hello = hello;
    }
    
    @Override
    public void sayHello() {
        System.out.println("Welcome!");
        hello.sayHello();
        System.out.println("Goodbye!");
    } 
}

Proxy.sayHello() 方法的实现会调用其中封装的 HelloImpl对象的 sayHello() 方法,执行真正的业务逻辑。代理的作用不仅仅是正常地完成业务逻辑,还会在业务逻辑前后添加一些代理逻辑,也就是说,Proxy.sayHello() 方法会在 HelloImpl.sayHello() 方法调用前后进行一些预处理以及一些后置处理。
代理对象可以协调真正HelloImpl对象与调用者之间的关系,在一定程度上实现了解耦的效果。


2.2 动态代理

为解决静态代理会产生大量代理类的问题,动态代理出现了
Java动态代理实现:

  1. JDK动态代理:利用JDK的Proxy类和InvocationHandler接口实现动态代理。代理对象在运行时创建,可以为多个目标对象提供代理服务。需要目标对象实现接口,代理类需要实现InvocationHandler并持有目标对象实例。
  2. CGLIB动态代理:利用ASM字节码操作生成代理类,不需要目标对象实现接口。目标类的方法会被拦截,并在方法执行前后执行代理逻辑。性能好于JDK动态代理。
  3. Javassist 动态代理:Javassist 是一个开源的生成 Java 字节码的类库,其主要优点在于简单、快速,直接使用Javassist 提供的 Java API 就能动态修改类的结构,或是动态生成类。

此处以JDK代理为例展开说明下
JDK 动态代理的核心是InvocationHandler 接口。这里提供一个 InvocationHandler 的Demo 实现,代码如下:

public interface Hello {
    void sayHello();
}

public class HelloInvocationHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Welcome!");  
        method.invoke(target, args);    
        System.out.println("Goodbye!");
        return null;
    }
}
public static void main(String[] args){
	Hello proxy = (Hello) Proxy.newProxyInstance(
	        HelloImpl.class.getClassLoader(), 
	        new Class[] {Hello.class}, 
	        new HelloInvocationHandler(new HelloImpl()));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值