能否让 Cache 变得更加优雅?

原创
2013/11/04 12:14
阅读数 3.3K

本文是《轻量级 Java Web 框架架构设计》的系列博文。

之前实现了一个简单的 Cache 插件,主要用于 Service 层,为了减少数据库的访问次数,将数据放入 Cache 中缓存起来。在 Service 中直接使用了 Cache API,这样导致 Service 代码变得更加复杂,Cache 逻辑与核心逻辑纠缠在一起,我想着应该是一个很明显的缺点吧具体的开发过程,请参考《Smart Plugin —— 从一个简单的 Cache 开始》。

后来 Bieber 对 Cache 做了一个优化,结合了 Spring Cache 的注解式配置,让 Service 中所涉及的 Cache 操作分离出来,充分利用了 AOP 的思想,通过使用 Smart 的 Aspect(切面类)来实现此功能。大家可以阅读这篇博文《Smart Framework 缓存插件的实现》。

我下面打算与大家交流的这样一个思路:

有些插件,比如:Cache、Log、Performance 等,实际上他们都带有 AOP 的色彩,都是为了在执行目标方法的前后分别做点事情。就 Cache 插件而言,它应该自己提供一个 Aspect,并将此 Aspect 融入到 Smart AOP 环境中,而无需在应用程序中,定义一个 Cache 的 Aspect(这样或许有些多余)。也就是说,Cache 插件的核心就是一个 Aspect,此外才是用于控制缓存的 API,而这些 API 是给插件自身来调用的,而不是给应用程序调用而已。

我想像这样来实现缓存:

@Bean
@Cachable
public class CustomerServiceImpl extends BaseService implements CustomerService {

    @Override
    @CachePut("customer_list_cache")
    public List<Customer> getCustomerList() {
        return DataSet.selectList(Customer.class, null, null);
    }

    @Override
    @CacheClear({"customer_list_cache", "customer_cache"})
    public boolean deleteCustomer(long id) {
        return DataSet.delete(Customer.class, "id = ?", id);
    }

    @Override
    @CachePut("customer_cache")
    public Customer getCustomer(long id) {
        return DataSet.select(Customer.class, "id = ?", id);
    }

    @Override
    @CacheClear({"customer_list_cache", "customer_cache"})
    public boolean updateCustomer(long id, Map<String, Object> fieldMap) {
        return DataSet.update(Customer.class, fieldMap, "id = ?", id);
    }

    @Override
    @CacheClear({"customer_list_cache", "customer_cache"})
    public boolean createCustomer(Map<String, Object> fieldMap) {
        return DataSet.insert(Customer.class, fieldMap);
    }
}

在以上代码中,在类上面使用了 Cachable 注解,说明这个类是具备缓存特性的(可缓存的)。在需要缓存的方法上,使用了 CachePut 注解或 CacheClear 注解,前者用于将数据放入缓存,后者用户从缓存中清空数据(也就是使缓存消失)。

例如,在 getCustomerList 方法中,使用了 CachePut 注解,在其注解参数中定义了 Cache 名称(customer_list_cache)。在实际运行时,先从 Cache 里获取数据,如果没有,则从 DB 中获取,最后将数据放回 Cache 中。这个逻辑都是在 Cache 插件中实现的。

又如,在 deleteCustomer 方法中,使用了 CacheClear 注解,此时定义了两个 Cache 名称(customer_list_cache 与 customer_cache)。需要说明的是,这个 Service 中存在两个 Cache,一个用于缓存 customerList 数据,另一个用于缓存 customer 数据。当删除一个 Customer 时,首先在 DB 中进行,然后刷新缓存,此时需要一并刷新所涉及到该 Customer 的所有 Cache,所以这里在 CacheClear 注解中定义了两个 Cache。

后面几个方法与以上两个方法类似。其实 Cache 要干的事情,也就这两个方面(此时没有考虑 Cache 的淘汰策略)。

我的问题是,这样的实现感觉粒度有些粗,因为控制的在方法级别上,有没有可能将 Cache 控制在方法的内部呢?实际情况我想或许会比这个案例复杂,大家认为这种方式可行吗?

期待朋友们的解惑......

展开阅读全文
加载中
点击加入讨论🔥(2) 发布并加入讨论🔥
打赏
2 评论
10 收藏
2
分享
返回顶部
顶部