第二篇 调整对象功能 第十章 - 代理模式

  我们再观察一下上一章《装饰模式》提到的“抽象装饰类”。

// 抽象装饰类
public abstract class EnhancedExpression implements Expressible {

  private Expressible obj;

  public EnhancedExpression(Expressible obj) {
    this.obj = obj;
  }

  @Override
  public void express() {
    this.obj.express();
  }

}

  它隐藏了 obj 对象,对外提供了自己的 express() 方法(下文称“#express()”)。
  我们不能直接执行 obj.express(),只好由 #express() 代劳。#express() 俨然成了 obj.express() 的替身与代理人,它可以拦截其它对象对 obj 的访问,还能增强或减弱甚至完全控制 obj 的功能。
  这种设计方法也被称为代理模式。完整的写法如下所示。

// 百工之人
public interface Doable {

   public void doIt();

}

// 实干家
public class Doer implements Doable {

  public void doIt() {}

}

// 代理类
public class Proxy implements Doable {

  private Doable obj;

  public Proxy(Doable obj) {
    this.obj = obj;
  }

  public void doIt() {
    this.before();// 前置方法
    this.obj.doIt();// 核心业务逻辑
    this.after();// 后置方法
  }

  private void before() {}

  private void after() {}

}

  代理模式被发现后,迅速成为耀眼的明星。它为我们带来了面向方面编程(Aspect-Oriented Programming,AOP)。
  AOP 允许我们将某个功能的不同方面散布在不同的类中,运行时再将它们组装起来。这有利于保持类职责的单一化,还保留了程序的灵活性。
  实践中常将核心业务逻辑与事务处理、安全控制、日志记录等系统公共服务分散开来。这些系统公共服务以代理类的形式出现,且能通过简捷的配置语法与核心业务逻辑组装在一起。
  下面是一个使用 Spring AOP 组件为某段核心业务逻辑增加日志记录特性的例子。

// 实干家
@Component
public class Doer {

  @Log // 增加日志记录特性
  public Object doIt(Object args) {
    return new Object();
  }

}

// 日志记录特性
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface Log {}

// 代理类
@Aspect
@Component
public class LogProxy {

  @Pointcut("@annotation(Log)")
  public void log() {}

  @Around("log()")
  public void around(ProceedingJoinPoint joinPoint) throws Throwable {
    this.before(joinPoint.getArgs());// 前置方法
    Object result = joinPoint.proceed();// 核心业务逻辑
    this.after(result);// 后置方法
  }

  private void before(Object[] args) {
    // Log the args.
  }

  private void after(Object result) {
    // Log the result.
  }

}
posted on 2025-03-23 20:08  星辰河岳  阅读(34)  评论(0)    收藏  举报