Mybatis 源码中的静态代理模式

静态代理模式

  • 代理模式(proxy)指的是为一个对象提供一个代理以控制外界对该对象的访问,比如有些情况下对象A不能直接访问对象B,此时可以为对象B创建一个代理C,然后对象A通过访问代理C来间接访问对象B。
  • 有的时候我们希望增强某个方法的功能,但是有不方便直接修改该方法,此时也可通过代理来实现,即在该方法执行的前后做一些事情。
  • 静态代理是指代理类和相关的方法直接在代码中写死。

Mybatis中使用静态代理的接口Executor

这里的代理类为 CachingExecutor,被代理类(目标类)为SimpleExecutor、ReuseExecutor或BatchExecutor

  • 代理类和被代理类实现相同的接口
  • 代理类维护被代理类的一个实例
  • 代理类实际上是调用被代理的方法,只是在方法调用前后添加一些功能
  • 代理类不会对目标类的代码进行修改

接口

public interface Executor {

  ResultHandler NO_RESULT_HANDLER = null;

  int update(MappedStatement ms, Object parameter) throws SQLException;

}
复制代码

被代理类

public abstract class BaseExecutor implements Executor {
    @Override
    public int update(MappedStatement ms, Object parameter) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
        if (closed) {
           throw new ExecutorException("Executor was closed.");
        }
        clearLocalCache();
        return doUpdate(ms, parameter);
    }
      
}
复制代码

代理类

public class CachingExecutor implements Executor {

  private Executor delegate;
  private TransactionalCacheManager tcm = new TransactionalCacheManager();

  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    delegate.setExecutorWrapper(this);
  }
  @Override
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
    // 重点,代理类增强的功能。这里是根据需要清空缓存
    flushCacheIfRequired(ms); 
    return delegate.update(ms, parameterObject);
  }
  
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    // 通过代理,加入缓存相关的逻辑。即启用缓存:有缓存直接返回,无缓存查数据库并加到缓存,不启用缓存:直接调用代理类的方法
    Cache cache = ms.getCache();
    if (cache != null) {
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, parameterObject, boundSql);
        @SuppressWarnings("unchecked")
        List<E> list = (List<E>) tcm.getObject(cache, key);
        if (list == null) {
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
  
}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值