RedCloud Help

代理模式

定义

为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和莫表对象之间起到中介作用,代理模式属于结构型设计模式。使用代理模式主要的两个目的:一保护目标对象,二增强目标对象。

代理模式类结构图

create
create
«interface»
Subject
request() : void
Proxy
Proxy(Subject)
request() : void
before() : void
after() : void
RealSubject
request() : void
Client
main(String []) : void

静态代理

  • 分布式场景下,配置多个数据源

    • OrderService插入数据库的Order的业务层

    • OrderServiceStaticProxy为OrderService中的代理类,在before中切换数据源

create
create
create
create
DynamicDataSourceEntry
clear() : void
get() : String
restore() : void
set(String) : void
set(int) : void
«interface»
IOrderService
createOrder(Order) : int
OrderServiceStaticProxy
createOrder(Order) : int
before() : void
after() : void
OrderService
createOrder(Order) : int
OrderDao
insert(Order) : int
DbRouteProxyTest
main(String []) : void
Order
getOrderInfo() : Object
setOrderInfo(Object) : void
getCreateTime() : Long
getCreateTime(Long) : void
getId() : String
setId(String) : void

动态代理

  • JDK实现方式

    • 拿到被代理对象的引用,并且获取到它的所有的接口,反射获取。

    • jdk proxy类重新生成一个新的类、同时新的类要实现被代理类所有实现的所有的接口

    • 动态生成Java代码,把新加的业务逻辑方法由一定的逻辑代码去调用

    • 编译新生成的Java代码。class

    • 在重新加载到就jvm中运行

create
newProxyInstance
create
«interface»
Person
findLove() : void
Girl
findLove() : void
«interface»
InvocationHandler
invoke(Object proxy,Method method,Object[] args) : Object
JDKMeipo
invoke(Object proxy,Method method,Object[] args) : Object
getInstance(Girl) : ProxyObject
Proxy
newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h) : Object
Client
main(String[]args) : void

CGlib动态代理

  • 会生成三个新的class文件

    • 重写代理对象的所有方法。集成代理对象。

    • 重写findLove方法,如果interceptor不为空,就走代理方法。

create
Customer
findLove() : void
Enhancer
setSuperclass(Customer)
setCallback()
create() : Object
CGlibMeipo
intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) : Object
before() : void
after() : void
MethodInterceptor
intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) : Object

CGLib和JDK动态代理对比

  1. JDK动态代理是实现了被代理对象的接口,CGLib是集成了被代理对象。

  2. JDK和CGLib都是在运行期生成字节码,JDK是直接写Class字节码,CGLib使用ASM框架写CLass字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。

  3. JDK调用代理对象方法,是通过反射机制调用,CGLib是通过FastClass机制直接调用方法,CGlib执行效率更高。

Spring中的代理模式

CglibAopProxy
AopProxy
Serializable
JdkDynamicAopProxy
«interface»
InvocationHandler

spring 中的代理选择原则

  1. 当Bean有实现接口时,spring就会用JDK的动态代理

  2. 当Bean没有实现接口时,SPring选择CGLib

  3. Spring可以通过配置强制使用CGlib,只需在Spring的配置文件中加入如下代码:

<aop:aspectj-autoproxy proxy-target-class="true"/>

静态代理和动态代理的配置区别

  1. 静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步新增,违背开闭原则

  2. 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则

  3. 若动态代理要对目标类的增加逻辑扩展,结合策略模式,只需要新增策略类便可完成,无需修改代理类的代码

代理模式的优缺点

  1. 代理模式能将代理对象与真实被调用的目标对象分离

  2. 一定程度上降低了系统的耦合度,扩展性好

  3. 可以起到保护目标对象的作用

  4. 可以对目标对象的功能增加

  1. 代理模式会造成系统设计中的类的数量增加。

  2. 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢

  3. 增加了系统的复杂度

13 February 2026