代理模式

1. 使用场景

需要在调用者和被调用者之间加入各种控制,分离XX关注点,实现面向切面编程。

2. 实现举例

1) 权限控制

spring security当中,可以对目标对象方法执行前作权限检查,通过@PreAuthorize注解控制。 加了这个注解的方法所在类,spring security会为之创建代理对象,客户真正执行的是代理对象中的方法;而代理对象中再对@PreAuthorize注解进行检查,如果有权限才间接调用目标对象方法,没权限就阻止目标对象方法的执行。

结论: 代理分离了权限关注点

2) 缓存控制

spring 当中,可以通过@Cacheable对目标方法的返回结果进行缓存控制。 加了这个注解的方法所在类,spring会为之创建代理对象,客户真正执行的是代理对象中的方法;而代理对象执行时再对@Cacheable注解进行解释,如果缓存中没有命中,才间接调用目标对象方法,将返回结果放入缓存;如果缓存命中,则直接返回缓存结果,而不会执行目标对象方法。

结论: 代理分离了缓存关注点

3) 事务控制

spring 当中,可以通过@Transactional对目标方法执行前后的事务进行控制, 加了这个注解的方法所在类,spring会为之创建代理对象,客户真正执行的是代理对象中的方法;而代理对象执行时再对@Transactional注解进行解释,在方法执行之前是开始新事务还是加入已有事务,根据方法执行是否出现了异常来决定是提交还是回滚事务。

结论: 代理分离了事务关注点

4) 方法远程调用

在方法的远程调用场景下,调用者只需像本地方法调用一样使用接口方法。

结论: 代理分离了远程访问关注点

5) 延迟实例化

比较典型的例子是hibernate做@ManyToOne的关系映射时,为了避免产生同时进行两张表的连接查询操作,hibernate为加了@ManyToOne的关系属性生成了代理对象。当没有用到关系属性对应的关系表数据时,不执行sql查询关系表,当第一次需要关系表数据时,才由代理对象发起一条查询语句去查关系表,从而实现了按需查询。

结论: 代理分离了延迟实例化关注点

6) 生命周期管理

有些对象的生命周期与调用者不同,需要协调。例如spring中要将生命周期较短(例如加了@RequestScope)的对象注入到生命周期更长的controller对象中。这时spring也是生成一个代理注入给controller,代理对象为每次请求生成新的对象注入给controller

结论: 代理分离了生命周期关注点

3. 特点

  • 代理模式需要代理和被代理类均实现相同的接口,或者代理类作为被代理类的子类
  • 代理类不会扩展原有接口或父类的功能,只是将某部分功能分出去
  • 代理类一般配合工厂使用来隐藏代理对象的创建细节
  • 产生代理类的手段有JDK动态代理、cglib、javassist等

results matching ""

    No results matching ""