发表于: 2017-07-18 22:18:51

2 1113


今天完成的事情:学习了一下spring cache,明天小课堂就准备讲这个了

spring cache简介

Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。

Spring 的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如 EHCache 集成。

其特点总结如下:

通过少量的配置 annotation 注释即可使得既有代码支持缓存

支持开箱即用 Out-Of-The-Box,即不用安装和部署额外第三方组件即可使用缓存

支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的 key 和 condition

支持 AspectJ,并通过其实现任何方法的缓存支持

支持自定义 key 和自定义缓存管理者,具有相当的灵活性和扩展性


具体案例

首先定义一个实体类:账号类,具备基本的 id 和 name 属性,且具备 getter 和 setter 方法

public class Account {

private int id;
   private String name;

   public Account(String name) {
this.name = name;
   }
public int getId() {
return id;
   }
public void setId(int id) {
this.id = id;
   }
public String getName() {
return name;
   }
public void setName(String name) {
this.name = name;
   }

}

然后定义一个缓存管理器,这个管理器负责实现缓存逻辑,支持对象的增加、修改和删除,支持值对象的泛型。如下:

import com.google.common.collect.Maps;

import java.util.Map;

/**
* @author wenchao.ren
*         2015/1/5.
*/
public class CacheContext<T> {

private Map<String, T> cache = Maps.newConcurrentMap();

   public T get(String key){
return  cache.get(key);
   }

public void addOrUpdateCache(String key,T value) {
cache.put(key, value);
   }

// 根据 key 来删除缓存中的一条记录
   public void evictCache(String key) {
if(cache.containsKey(key)) {
cache.remove(key);
       }
}

// 清空缓存中的所有记录
   public void evictCache() {
cache.clear();
   }

}

有了实体类和一个缓存管理器,还需要一个提供账号查询的服务类,此服务类使用缓存管理器来支持账号查询缓存,如下:

import com.google.common.base.Optional;
import com.rollenholt.spring.cache.example1.Account;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class AccountService3 {

private final Logger logger = LoggerFactory.getLogger(AccountService3.class);

   // 使用了一个缓存名叫 accountCache
   @Cacheable(value="accountCache")
public Account getAccountByName(String accountName) {

// 方法内部实现不考虑缓存逻辑,直接实现业务
       logger.info("real querying account... {}", accountName);
       Optional<Account> accountOptional = getFromDB(accountName);
       if (!accountOptional.isPresent()) {
throw new IllegalStateException(String.format("can not find account by account name : [%s]", accountName));
       }

return accountOptional.get();
   }

@CacheEvict(value="accountCache",key="#account.getName()")
public void updateAccount(Account account) {
updateDB(account);
   }

@CacheEvict(value="accountCache",allEntries=true)
public void reload() {
}

private void updateDB(Account account) {
logger.info("real update db...{}", account.getName());
   }

private Optional<Account> getFromDB(String accountName) {
logger.info("real querying db... {}", accountName);
       //Todo query data from database
       return Optional.fromNullable(new Account(accountName));
   }
}

测试用例

import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import static org.junit.Assert.*;

public class AccountService1Test {

private AccountService1 accountService1;

   private final Logger logger = LoggerFactory.getLogger(AccountService1Test.class);

   @Before
   public void setUp() throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
       accountService1 = context.getBean("accountService1", AccountService1.class);
   }

@Test
   public void testInject(){
assertNotNull(accountService1);
   }

@Test
   public void testGetAccountByName() throws Exception {
accountService1.getAccountByName("accountName");
       accountService1.getAccountByName("accountName");

       accountService1.reload();
       logger.info("after reload ....");

       accountService1.getAccountByName("accountName");
       accountService1.getAccountByName("accountName");
   }
}


明天计划的事情:讲小课堂,任务6。

遇到的问题:老大发话了,我要做5个分院的片头.......

收获:你们有毒都跑了


返回列表 返回列表
评论

    分享到