注意:配置一定要正确,Cache对象相关注解一定要在spring管理的其他对象中调用,不能是引用内部方法调用,因为缓存切面靠的就是代理proxy机制完成的。
配置
<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="com.finance.cache.DuoTalkTimesCache" p:name="duoTalkTimesCache"/>
set>
property>
bean>
Controller
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public int getTalkTimes() {
int x = duoTalkTimesDao.annotationCacheGet("duoduo");
return x;
}
@ResponseBody
@RequestMapping(value = "/put", method = RequestMethod.GET)
public String putTaslTimes() {
Integer 消息= duoTalkTimesDao.annotationCachePut("duoduo");
return String.valueOf(消息);
}
Repository
@Service
public class DuoTalkTimesDao {
@Resource
private DuoTalkTimesCache duoTalkTimesCache;
/**
* 将结果缓存,一定会执行db操作
* @param key
* @return
*/
@CachePut(value = "duoTalkTimesCache")
public Integer annotationCachePut(String key) {
System.out.println("更新数据库");// 模拟走数据库
return new Random().nextInt(10);
}
/**
* 根据key 去取缓存结果,如果有不走db操作,否则执行db操作,并将结果缓存。
* @param key
* @return
*/
@Cacheable(value = "duoTalkTimesCache")
public Integer annotationCacheGet(String key) {
System.out.println("查询数据库");//模拟查询数据库
return new Random().nextInt(10);
}
}
Cache
@Service
public class DuoTalkTimesCache implements Cache {
private static final Logger log = LoggerFactory.getLogger(DuoTalkTimesCache.class);
private static String talktimes = "0";
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public Object getNativeCache() {
return null;
}
@Override
public ValueWrapper get(Object key) {
Integer integer = get(key, Integer.class);
log.info("get first by key {}", key);
return integer == null ? null : new SimpleValueWrapper(integer);
}
@Override
public T get(Object key, Class type) {
log.info("get by key {}", key);
if (key == null || !(key instanceof String)) {
return null;
}
String value = talktimes;//from cache
if (StringUtils.isBlank(value)) {
return null;
}
return type.cast(Integer.parseInt(value));
}
@Override
public void put(Object key, Object value) {
log.info("put by key {} {}", key, value);
if (key == null || !(key instanceof String)) {
log.info("put by key {} {}", key, value);
return;
}
if (value == null || !(value instanceof Integer)) {
log.info("put by key {} {}", key, value);
return;
}
try {
//写入缓存
talktimes = String.valueOf(Integer.parseInt(talktimes) + (Integer) value);
log.info("put by key {} result = {}", key, talktimes);
} catch (Exception e) {
log.error("入缓存失败", e);
}
}
@Override
public void evict(Object key) {
log.info("get by key {}", key);
if (key == null || !(key instanceof String)) {
return;
}
try {
//删除缓存
} catch (Exception e) {
log.error("evict exception", e);
}
}
@Override
public void clear() {
//清空
}
}
SpEl:表达式两种用法
SpEL expressions can be used with XML or annotation-based configuration metadata for defining BeanDefinitions. In both cases the syntax to define the expression is of the form #{ }.
//XML
"numberGuess" class="org.spring.samples.NumberGuess">
"randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
"taxCalculator" class="org.spring.samples.TaxCalculator">
"defaultLocale" value="#{ systemProperties['user.region'] }"/>
//注解
public static class FieldValueTestBean
@Value("#{ systemProperties['user.region'] }")
private String defaultLocale;
public void setDefaultLocale(String defaultLocale) {
this.defaultLocale = defaultLocale;
}
public String getDefaultLocale() {
return this.defaultLocale;
}
}
@Cacheable(value="accountCache")// 使用了一个缓存名叫 accountCache
public Account getAccountByName(String userName) {
// 方法内部实现不考虑缓存逻辑,直接实现业务
return getFromDB(userName);
}
@CachePut(value="accountCache",key="#account.getName()")// 更新 accountCache 缓存
public Account updateAccount(Account account) {
return updateDB(account);
}
private Account updateDB(Account account) {
System.out.println("real updating db..."+account.getName());
return account;
}