请移步: http://hacpai.com/article/1376986299174
在对项目进行优化的时候,我们可以主要从以下三个方面入手:
1 缓存
2 集群
3 异步
今天,就先说说缓存。先说说spring的缓存,下一节我们再聊聊redis
说到spring的缓存,得提到三个注解。
@Cacheable(value="accountCache")
public Account getAccountByName(String accountName) {
System.out.println("我进来了");
// 方法内部实现不考虑缓存逻辑,直接实现业务
logger.info("real querying account... {}", accountName);
Account accountOptional = getFromDB(accountName);
return accountOptional;
}
@CacheEvict(value="accountCache",key="#account.getName()")
public Account updateAccount(Account account) {
return updateDB(account);
}
上面的意思是说,如果一旦调用了updateAccount这个方法,spring就会通过参数的getName方法获得一个值,并且用这个值删除accountCache中的某一个key。
@CacheEvict(value="accountCache",allEntries=true)
public void reload() {
}
参数allEntyies=true是什么意思,还用我说么?
@CachePut(value="accountCache",key="#account.getName()")
public Account updateAccount(Account account) {
return updateDB(account);
}
上面的 @CachePut的意思就是说,一旦我调用updateAccount方法,spring就会通过getName()取得account参数的一个值,并且以这个值为key,以updateAccount的返回值为value,更新accountCache。
@Cacheable(value="accountCache",condition="#accountName.length() <= 4")
public Account getAccountByNameWithCondition(String accountName) {
// 方法内部实现不考虑缓存逻辑,直接实现业务
return getFromDB(accountName);
}
condaition会返回一个boolean值,如果是true,才进行缓存操作。
@Cacheable(value="accountCache",key="#accountName.concat(#password)")
public Account getAccount(String accountName,String password,boolean other) {
// 方法内部实现不考虑缓存逻辑,直接实现业务
return getFromDB(accountName,password);
}
首先说明额,那个concat是java中String类的原生方法。
import java.util.Map;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
public class MyCache implements Cache {
private String name;
private Map store = new HashMap();;
public MyCache() {
}
public MyCache(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object getNativeCache() {
return store;
}
@Override
public ValueWrapper get(Object key) {
ValueWrapper result = null;
Account thevalue = store.get(key);
if(thevalue!=null) {
thevalue.setPassword("from mycache:"+name); //注意这一行
result = new SimpleValueWrapper(thevalue);
}
return result;
}
@Override
public void put(Object key, Object value) {
Account thevalue = (Account)value;
store.put((String)key, thevalue);
}
@Override
public void evict(Object key) {
}
@Override
public void clear() {
}
}
再看CacheManager
import java.util.Collection;
import org.springframework.cache.support.AbstractCacheManager;
public class MyCacheManager extends AbstractCacheManager {
private Collection extends MyCache> caches;
/**
* Specify the collection of Cache instances to use for this CacheManager.
*/
public void setCaches(Collection extends MyCache> caches) {
this.caches = caches;
}
@Override
protected Collection extends MyCache> loadCaches() {
return this.caches;
}
}
上面的一切都已经OK,当然spring还不知道我们干的事情
当我们用下面的代码测试的时候:
@Test
public void getCacheMySelf(){
Account account = accountService6.getAccountByName("someone");
System.out.println("***");
logger.info("passwd={}", account.getPassword());
account = accountService6.getAccountByName("someone");
logger.info("passwd={}", account.getPassword());
}
输出如下:
INFO 2015-12-04 21:07:01,695 cache.springannotation.step6.AccountService6:26 --- real querying account... someone
INFO 2015-12-04 21:07:01,697 cache.springannotation.step6.AccountService6:60 --- real querying db... someone
***
INFO 2015-12-04 21:07:01,697 cache.springannotation.step6.AccountService6Test:74 --- passwd=null
INFO 2015-12-04 21:07:01,698 cache.springannotation.step6.AccountService6Test:76 --- passwd=from mycache:accountCache
简单的说:
spirng默认的缓存不支持内部调用
而且要缓存的方法必须是public的
就在刚才
glt想我了
glt是谁? 我媳妇
嘿嘿
参考资料: