/**
|
* Copyright (c) 2013-2021 Nikita Koksharov
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
package com.dl.framework.manager;
|
|
import com.dl.common.utils.redis.RedisUtils;
|
import org.redisson.api.RMap;
|
import org.redisson.api.RMapCache;
|
import org.redisson.spring.cache.CacheConfig;
|
import org.redisson.spring.cache.RedissonCache;
|
import org.springframework.boot.convert.DurationStyle;
|
import org.springframework.cache.Cache;
|
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
|
import org.springframework.util.StringUtils;
|
|
import java.util.Collection;
|
import java.util.Collections;
|
import java.util.Map;
|
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentMap;
|
|
/**
|
* A {@link org.springframework.cache.CacheManager} implementation
|
* backed by Redisson instance.
|
* <p>
|
* 修改 RedissonSpringCacheManager 源码
|
* 重写 cacheName 处理方法 支持多参数
|
*
|
* @author Nikita Koksharov
|
*
|
*/
|
@SuppressWarnings("unchecked")
|
public class PlusSpringCacheManager implements CacheManager {
|
|
private boolean dynamic = true;
|
|
private boolean allowNullValues = true;
|
|
private boolean transactionAware = true;
|
|
Map<String, CacheConfig> configMap = new ConcurrentHashMap<>();
|
ConcurrentMap<String, Cache> instanceMap = new ConcurrentHashMap<>();
|
|
/**
|
* Creates CacheManager supplied by Redisson instance
|
*/
|
public PlusSpringCacheManager() {
|
}
|
|
|
/**
|
* Defines possibility of storing {@code null} values.
|
* <p>
|
* Default is <code>true</code>
|
*
|
* @param allowNullValues stores if <code>true</code>
|
*/
|
public void setAllowNullValues(boolean allowNullValues) {
|
this.allowNullValues = allowNullValues;
|
}
|
|
/**
|
* Defines if cache aware of Spring-managed transactions.
|
* If {@code true} put/evict operations are executed only for successful transaction in after-commit phase.
|
* <p>
|
* Default is <code>false</code>
|
*
|
* @param transactionAware cache is transaction aware if <code>true</code>
|
*/
|
public void setTransactionAware(boolean transactionAware) {
|
this.transactionAware = transactionAware;
|
}
|
|
/**
|
* Defines 'fixed' cache names.
|
* A new cache instance will not be created in dynamic for non-defined names.
|
* <p>
|
* `null` parameter setups dynamic mode
|
*
|
* @param names of caches
|
*/
|
public void setCacheNames(Collection<String> names) {
|
if (names != null) {
|
for (String name : names) {
|
getCache(name);
|
}
|
dynamic = false;
|
} else {
|
dynamic = true;
|
}
|
}
|
|
/**
|
* Set cache config mapped by cache name
|
*
|
* @param config object
|
*/
|
public void setConfig(Map<String, ? extends CacheConfig> config) {
|
this.configMap = (Map<String, CacheConfig>) config;
|
}
|
|
protected CacheConfig createDefaultConfig() {
|
return new CacheConfig();
|
}
|
|
@Override
|
public Cache getCache(String name) {
|
Cache cache = instanceMap.get(name);
|
if (cache != null) {
|
return cache;
|
}
|
if (!dynamic) {
|
return cache;
|
}
|
|
CacheConfig config = configMap.get(name);
|
if (config == null) {
|
config = createDefaultConfig();
|
configMap.put(name, config);
|
}
|
|
// 重写 cacheName 支持多参数
|
String[] array = StringUtils.delimitedListToStringArray(name, "#");
|
name = array[0];
|
if (array.length > 1) {
|
config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis());
|
}
|
if (array.length > 2) {
|
config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis());
|
}
|
if (array.length > 3) {
|
config.setMaxSize(Integer.parseInt(array[3]));
|
}
|
|
if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) {
|
return createMap(name, config);
|
}
|
|
return createMapCache(name, config);
|
}
|
|
private Cache createMap(String name, CacheConfig config) {
|
RMap<Object, Object> map = RedisUtils.getClient().getMap(name);
|
|
Cache cache = new RedissonCache(map, allowNullValues);
|
if (transactionAware) {
|
cache = new TransactionAwareCacheDecorator(cache);
|
}
|
Cache oldCache = instanceMap.putIfAbsent(name, cache);
|
if (oldCache != null) {
|
cache = oldCache;
|
}
|
return cache;
|
}
|
|
private Cache createMapCache(String name, CacheConfig config) {
|
RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name);
|
|
Cache cache = new RedissonCache(map, config, allowNullValues);
|
if (transactionAware) {
|
cache = new TransactionAwareCacheDecorator(cache);
|
}
|
Cache oldCache = instanceMap.putIfAbsent(name, cache);
|
if (oldCache != null) {
|
cache = oldCache;
|
} else {
|
map.setMaxSize(config.getMaxSize());
|
}
|
return cache;
|
}
|
|
@Override
|
public Collection<String> getCacheNames() {
|
return Collections.unmodifiableSet(configMap.keySet());
|
}
|
|
|
}
|