代理模式学习笔记

代理模式

Proxy

根据下面的文章学习代理模式

https://juejin.im/post/5a99048a6fb9a028d5668e62#heading-0

https://juejin.im/post/5dec590551882512480a76e3

我们的目标:增强方法,尤其是在一些封装好,不能直接修改原方法的情况下,对方法进行增强。

解决方案

a)继承

最直观解决方案

b)聚合(静态代理)

与继承同样是java类五大关系之一

利用多态的特性

典型的静态代理

静态代理至少有以下两个局限性问题:

  • 如果同时代理多个类,依然会导致类无限制扩展
  • 如果类中有多个方法,同样的逻辑需要反复实现

比如假如要增强100个方法,就要起码写100个代理类

那么,我们是否可以使用同一个代理类来代理任意对象呢?

起码一个特定代理类能给任意方法增强一个特定功能?

c)动态代理

难理解,因为方式比较大胆,

是否可以使用同一个类(例如:TimeProxy)来计算任意对象的任一方法的执行时间呢。

这个部分需要一定的抽象思维,我想,你脑海中的第一个解决方案应该是使用反射。反射是用于获取已创建实例的方法或者属性,并对其进行调用或者赋值。很明显,在这里,反射解决不了问题。

但是,再大胆一点,如果我们可以动态生成TimeProxy这个类,并且动态编译。然后,再通过反射创建对象并加载到内存中,不就实现了对任意对象进行代理了吗?

个人理解:运行时再生成代理类,然后再生成Proxy对象。以前手写的 TimeProxy.java用 Proxy .java 自动生成了,虽然Proxy .java看着也很复杂

第一步:(动态)生成TimeProxy源码

第二步:(动态)编译TimeProxy源码

第三步:加载到内存中并创建对象

通过以上三个步骤,我们至少解决了下面两个问题:

  • 不再需要手动创建TimeProxy

    (手动创建了Proxy类)

  • 可以代理任意实现了Flyable接口的类对象,并获取接口方法的执行时间

    (就是给任意实现了Flyable接口的类对象所实现的接口方法增加了一个功能)

现在的问题

  • 一个Proxy类针对一个功能(记录方法运行时间)动态生成,想增强别的功能得再写个Proxy类
  • Proxy类里写死了生成的类的接口类型(改成由 newProxyInstance(Class inf) 传递参数确定接口类型就行就可以了)

第四步:增加InvocationHandler接口

 public interface InvocationHandler {    
     void invoke(Object proxy, Method method, Object[] args); 
 } 
  • proxy => 这个参数指定动态生成的代理类,这里是TimeProxy
  • method => 这个参数表示传入接口中的所有Method对象
  • args => 这个参数对应当前method方法中的参数

为此,我们需要在Proxy.newProxyInstance()方法中做如下改动:

  • 在newProxyInstance()方法中加一个参数传入InvocationHandler
  • 在生成的代理类中增加成员变量handler
  • 在生成的代理类方法中,调用invoke方法

然后实现InvocationHandler接口, MyInvocationHandler 类, invoke方法里实现要添加的功能。

tip:因为要用到反射,反射里也有invoke方法,不要搞混 !

其实Proxy和InvocationHandler接口不用自己写,JDK自带,跟那个博客里写的差不多,只有些细节上的区别,比如为了方便链式编程返回值返回对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值