JDK原生实现动态代理
由上一篇中的代理模式UML类图我们可以看出,代理类和被代理类需要依赖统一接口,代理类通过在接口方法的实现中增加增强逻辑并调用被代理类的实现,实现代理。这样客户端在调用的时候,代理类便可以替代被代理类,并且对外的调用接口相同。
静态代理的局限性上篇博文中已经介绍过,即接口声明的方法过多的时候,我们需要逐一进行增强添加,这样在需求变更或者接口更改的时候就会非常麻烦。
动态代理在静态代理的基础上,通过Java提供的类通过反射在运行时动态获得接口信息,并对其进行增强。我们先看一个小例子:
反观上例,我们在创建动态代理的过程中。实际上是自己实现一个实现了InvocationHandler的拦截器
(这里的拦截器只是一种比喻,该说法不准确),其中包含一个被代理类的实例引用。InvocationHandler
接口中只有一个invoke(Object proxy, Method method, Object[] args)
方法,我们便在该方法中实现对于方法的增强。并在实现增强后,调用被代理类的方法。
在使用时,我们首先创建proxy对象。该对象关联一个自定义InvocationHandler
对象和一个被代理对象
。我们调用代理对象的方法时,会转向调用InvocationHandler中的invoke方法。这也就实现了代码的增强(理解起来和Spring AOP类似)。
JDK原生动态代理总结
在InvocationHandler的实现中,我们可以看到,我们可以对所有方法添加公共的增强;同时也可以针对方法增加特定的增强,这有着很大的灵活性。这也是动态代理的优点之一。但是仔细观察代码实现的原理,JDK原生动态代理是通过反射获得被代理对象所实现的接口方法,并对这些接口方法进行代理和增强。虽然相比静态代理,其免去了需要逐一代理,且当被代理对象实现多个接口的时候,无需为每一个接口创建一个代理类;但是其实现仍然受到接口的约束。这也是动态代理的不足之处。
下一篇博文中,将介绍有关使用cglib代码生成库实现动态代理的原理及方法。相比于JDK原生动态代理,cglib具有更大的灵活性。