我试图说服我的公司使用spring 3.2的缓存(我知道它已经很老了)。
该应用程序构建于顶级露天5.x(构建于3.2之上)。
目前,我们有一些绑定到当前交易的缓存:
if (AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY) {
cache = (Map<String, Boolean>) AlfrescoTransactionSupport.getResource(CACHED_NAME);
if (cache == null) {
cache = new HashMap<String, Boolean>();
}
AlfrescoTransactionSupport.bindResource(CACHED_NAME, cache);
}
缓存仅对当前读取事务有效,然后被销毁。
我试过了
@Cacheable("cache_name")
@Transactional(readOnly=true)
注释,但是当读写事务打开时,缓存不会被销毁。
知道如何以春季的方式做到这一点吗?
答案 0 :(得分:0)
@biiyamn是对的,
我必须实现自己的缓存才能做到这一点。
首先,我实现了BeanFactory:
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
public class KReadTransactionCacheFactoryBean implements FactoryBean<KReadTransactionCache>, BeanNameAware,
InitializingBean {
private String name = "";
private boolean allowNullValues = true;
private KReadTransactionCache cache;
/**
* Specify the name of the cache.
* <p>Default is "" (empty String).
*/
public void setName(String name) {
this.name = name;
}
/**
* Set whether to allow {@code null} values
* (adapting them to an internal null holder value).
* <p>Default is "true".
*/
public void setAllowNullValues(boolean allowNullValues) {
this.allowNullValues = allowNullValues;
}
public void setBeanName(String beanName) {
if (!StringUtils.hasLength(this.name)) {
setName(beanName);
}
}
public void afterPropertiesSet() {
this.cache = new KReadTransactionCache(this.name, this.allowNullValues);
}
public KReadTransactionCache getObject() {
return this.cache;
}
public Class<?> getObjectType() {
return KReadTransactionCache.class;
}
public boolean isSingleton() {
return false;
}
}
然后,实施de cache to binded to current transaction
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
public class KReadTransactionCache implements Cache {
private static final Object NULL_HOLDER = new NullHolder();
private final String name;
private final boolean allowNullValues;
/**
* Create a new ConcurrentMapCache with the specified name.
* @param name the name of the cache
*/
public KReadTransactionCache(String name) {
this(name, true);
}
protected static Map<Object, Object> getBindedCache(String name) {
Map<Object, Object> cache = null;
if (AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY) {
cache = AlfrescoTransactionSupport.getResource(name);
if (cache == null) {
cache = new HashMap<>();
}
AlfrescoTransactionSupport.bindResource(name, cache);
}
return cache;
}
/**
* Create a new Map with the specified name and the
* given internal ConcurrentMap to use.
* @param name the name of the cache
* @param allowNullValues whether to allow {@code null} values
* (adapting them to an internal null holder value)
*/
public KReadTransactionCache(String name, boolean allowNullValues) {
this.name = name;
this.allowNullValues = allowNullValues;
}
public String getName() {
return this.name;
}
public Map getNativeCache() {
return getBindedCache(name);
}
public boolean isAllowNullValues() {
return this.allowNullValues;
}
public ValueWrapper get(Object key) {
final Map<Object, Object> bindedCache = getBindedCache(name);
if (bindedCache == null) {
return null;
}
Object value = bindedCache.get(key);
return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null);
}
public void put(Object key, Object value) {
final Map<Object, Object> bindedCache = getBindedCache(name);
if (bindedCache == null) {
return;
}
bindedCache.put(key, toStoreValue(value));
}
public void evict(Object key) {
final Map<Object, Object> bindedCache = getBindedCache(name);
if (bindedCache == null) {
return;
}
bindedCache.remove(key);
}
public void clear() {
final Map<Object, Object> bindedCache = getBindedCache(name);
if (bindedCache == null) {
return;
}
bindedCache.clear();
}
/**
* Convert the given value from the internal store to a user value
* returned from the get method (adapting {@code null}).
* @param storeValue the store value
* @return the value to return to the user
*/
protected Object fromStoreValue(Object storeValue) {
if (this.allowNullValues && storeValue == NULL_HOLDER) {
return null;
}
return storeValue;
}
/**
* Convert the given user value, as passed into the put method,
* to a value in the internal store (adapting {@code null}).
* @param userValue the given user value
* @return the value to store
*/
protected Object toStoreValue(Object userValue) {
if (this.allowNullValues && userValue == null) {
return NULL_HOLDER;
}
return userValue;
}
@SuppressWarnings("serial")
private static class NullHolder implements Serializable {
}
}
xml配置:
<!-- *******************************
***** CACHE CONFIGURATION *****
******************************* -->
<!-- simple cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default" />
<bean class="path.to.package.KReadTransactionCacheFactoryBean" p:name="cacheNameByAnnotation" />
<!-- TODO Add other cache instances in here -->
</set>
</property>
</bean>
答案 1 :(得分:0)