Skip to content
This repository was archived by the owner on Nov 21, 2020. It is now read-only.

Commit dc7b169

Browse files
committed
feat: simplify spring cache
1 parent 39f9b19 commit dc7b169

File tree

6 files changed

+324
-0
lines changed

6 files changed

+324
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.code4everything.boot.cache;
2+
3+
import cn.hutool.core.util.ObjectUtil;
4+
import org.springframework.cache.Cache;
5+
import org.springframework.cache.CacheManager;
6+
7+
import java.util.*;
8+
import java.util.concurrent.ConcurrentHashMap;
9+
10+
/**
11+
* 缓存管理器
12+
*
13+
* @author pantao
14+
* @since 2019/6/13
15+
**/
16+
public class BootCacheManager implements CacheManager {
17+
18+
protected final Map<String, Cache> cacheMap;
19+
20+
protected final Set<String> cacheNames;
21+
22+
protected final CacheCreator cacheCreator;
23+
24+
protected final boolean dynamic;
25+
26+
public BootCacheManager(CacheCreator cacheCreator) {
27+
this(cacheCreator, 16);
28+
}
29+
30+
public BootCacheManager(CacheCreator cacheCreator, int capacity) {
31+
Objects.requireNonNull(cacheCreator, "cache creator must not be null");
32+
this.dynamic = true;
33+
this.cacheCreator = cacheCreator;
34+
cacheMap = new ConcurrentHashMap<>(capacity);
35+
cacheNames = new HashSet<>(capacity);
36+
}
37+
38+
public BootCacheManager(Collection<Cache> caches, CacheCreator cacheCreator) {
39+
Objects.requireNonNull(caches, "cache list must not null null");
40+
this.dynamic = ObjectUtil.isNotNull(cacheCreator);
41+
this.cacheCreator = cacheCreator;
42+
int capacity = caches.size() * 4 / 3 + 1;
43+
cacheMap = new ConcurrentHashMap<>(capacity);
44+
cacheNames = new HashSet<>(capacity);
45+
caches.forEach(cache -> {
46+
cacheMap.put(cache.getName(), cache);
47+
cacheNames.add(cache.getName());
48+
});
49+
}
50+
51+
public BootCacheManager(Collection<Cache> caches) {
52+
this(caches, null);
53+
}
54+
55+
@Override
56+
public Cache getCache(String name) {
57+
Cache cache = cacheMap.get(name);
58+
if (cache == null && dynamic) {
59+
synchronized (cacheMap) {
60+
cache = cacheMap.get(name);
61+
if (cache == null) {
62+
cache = cacheCreator.createCache(name);
63+
cacheNames.add(name);
64+
}
65+
}
66+
}
67+
return cache;
68+
}
69+
70+
@Override
71+
public Collection<String> getCacheNames() {
72+
return cacheNames;
73+
}
74+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.code4everything.boot.cache;
2+
3+
import org.springframework.cache.Cache;
4+
5+
/**
6+
* 缓存创建者
7+
*
8+
* @author pantao
9+
* @since 2019/6/13
10+
**/
11+
public interface CacheCreator {
12+
13+
/**
14+
* 创建缓存
15+
*
16+
* @param cacheName 缓存名
17+
*
18+
* @return 缓存
19+
*
20+
* @since 1.1.3
21+
*/
22+
Cache createCache(String cacheName);
23+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.code4everything.boot.cache;
2+
3+
import cn.hutool.core.collection.CollUtil;
4+
import com.google.common.cache.CacheBuilder;
5+
import org.code4everything.boot.cache.guava.GuavaCacheCreator;
6+
import org.code4everything.boot.cache.guava.GuavaCacheManager;
7+
import org.springframework.cache.Cache;
8+
9+
import java.util.ArrayList;
10+
import java.util.Arrays;
11+
import java.util.Collection;
12+
13+
/**
14+
* Spring Cache工具类
15+
*
16+
* @author pantao
17+
* @since 2019/6/13
18+
**/
19+
public class CacheUtils {
20+
21+
private CacheUtils() {}
22+
23+
public static GuavaCacheManager newGuavaCacheManager(CacheBuilder<Object, Object> cacheBuilder, String... names) {
24+
return newGuavaCacheManager(cacheBuilder, Arrays.asList(names));
25+
}
26+
27+
public static GuavaCacheManager newGuavaCacheManager(CacheBuilder<Object, Object> cacheBuilder,
28+
Collection<String> names) {
29+
CacheCreator cacheCreator = new GuavaCacheCreator(cacheBuilder);
30+
if (CollUtil.isEmpty(names)) {
31+
return new GuavaCacheManager(cacheCreator);
32+
}
33+
Collection<Cache> caches = new ArrayList<>(names.size());
34+
for (String name : names) {
35+
caches.add(cacheCreator.createCache(name));
36+
}
37+
return new GuavaCacheManager(caches, cacheCreator);
38+
}
39+
40+
public static BootCacheManager newCacheManager(CacheCreator cacheCreator, String... names) {
41+
return newCacheManager(cacheCreator, Arrays.asList(names));
42+
}
43+
44+
public static BootCacheManager newCacheManager(CacheCreator cacheCreator, Collection<String> names) {
45+
if (CollUtil.isEmpty(names)) {
46+
return new BootCacheManager(cacheCreator);
47+
}
48+
Collection<Cache> caches = new ArrayList<>(names.size());
49+
for (String name : names) {
50+
caches.add(cacheCreator.createCache(name));
51+
}
52+
return new BootCacheManager(caches, cacheCreator);
53+
}
54+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package org.code4everything.boot.cache.guava;
2+
3+
import com.google.common.cache.CacheBuilder;
4+
import org.code4everything.boot.config.BootConfig;
5+
import org.code4everything.boot.web.mvc.exception.ExceptionFactory;
6+
import org.springframework.cache.Cache;
7+
import org.springframework.cache.support.SimpleValueWrapper;
8+
import org.springframework.http.HttpStatus;
9+
10+
import java.util.Objects;
11+
import java.util.concurrent.Callable;
12+
13+
/**
14+
* 谷歌Guava缓存
15+
*
16+
* @author pantao
17+
* @since 2019/6/13
18+
**/
19+
public class GuavaCache implements Cache {
20+
21+
private final com.google.common.cache.Cache<Object, Object> cache;
22+
23+
private final String name;
24+
25+
public GuavaCache(String name, com.google.common.cache.Cache<Object, Object> cache) {
26+
this.name = name;
27+
this.cache = cache;
28+
}
29+
30+
public GuavaCache(String name, CacheBuilder<Object, Object> cacheBuilder) {
31+
this(name, cacheBuilder.build());
32+
}
33+
34+
@Override
35+
public String getName() {
36+
return name;
37+
}
38+
39+
@Override
40+
public Object getNativeCache() {
41+
return cache;
42+
}
43+
44+
@Override
45+
public ValueWrapper get(Object key) {
46+
Object value = cache.getIfPresent(key);
47+
return Objects.isNull(value) ? null : new SimpleValueWrapper(value);
48+
}
49+
50+
@Override
51+
@SuppressWarnings("unchecked")
52+
public <T> T get(Object key, Class<T> type) {
53+
return (T) cache.getIfPresent(key);
54+
}
55+
56+
@Override
57+
@SuppressWarnings("unchecked")
58+
public <T> T get(Object key, Callable<T> valueLoader) {
59+
Object value = cache.getIfPresent(key);
60+
if (Objects.isNull(value)) {
61+
try {
62+
return valueLoader.call();
63+
} catch (Exception e) {
64+
if (BootConfig.isDebug()) {
65+
throw ExceptionFactory.exception(HttpStatus.INTERNAL_SERVER_ERROR, "value loader error");
66+
}
67+
return null;
68+
}
69+
}
70+
return (T) value;
71+
}
72+
73+
@Override
74+
public void put(Object key, Object value) {
75+
cache.put(key, value);
76+
}
77+
78+
@Override
79+
public ValueWrapper putIfAbsent(Object key, Object value) {
80+
Object val = cache.getIfPresent(key);
81+
if (Objects.isNull(val)) {
82+
put(key, value);
83+
}
84+
return new SimpleValueWrapper(val);
85+
}
86+
87+
@Override
88+
public void evict(Object key) {
89+
cache.invalidate(key);
90+
}
91+
92+
@Override
93+
public void clear() {
94+
cache.invalidateAll();
95+
}
96+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.code4everything.boot.cache.guava;
2+
3+
import com.google.common.cache.CacheBuilder;
4+
import org.code4everything.boot.cache.CacheCreator;
5+
import org.springframework.cache.Cache;
6+
7+
import java.util.Objects;
8+
9+
/**
10+
* 谷歌Guava缓存创建者
11+
*
12+
* @author pantao
13+
* @since 2019/6/13
14+
**/
15+
public class GuavaCacheCreator implements CacheCreator {
16+
17+
private final CacheBuilder<Object, Object> cacheBuilder;
18+
19+
public GuavaCacheCreator(CacheBuilder<Object, Object> cacheBuilder) {
20+
Objects.requireNonNull(cacheBuilder, "guava cache builder must not be null");
21+
this.cacheBuilder = cacheBuilder;
22+
}
23+
24+
@Override
25+
public Cache createCache(String cacheName) {
26+
return new GuavaCache(cacheName, cacheBuilder.build());
27+
}
28+
29+
public CacheBuilder<Object, Object> getCacheBuilder() {
30+
return cacheBuilder;
31+
}
32+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.code4everything.boot.cache.guava;
2+
3+
import com.google.common.cache.CacheBuilder;
4+
import org.code4everything.boot.cache.BootCacheManager;
5+
import org.code4everything.boot.cache.CacheCreator;
6+
import org.springframework.cache.Cache;
7+
8+
import java.util.Collection;
9+
10+
/**
11+
* 谷歌Guava缓存管理器
12+
*
13+
* @author pantao
14+
* @since 2019/6/13
15+
**/
16+
public class GuavaCacheManager extends BootCacheManager {
17+
18+
public GuavaCacheManager(CacheBuilder<Object, Object> cacheBuilder) {
19+
this(cacheBuilder, 16);
20+
}
21+
22+
public GuavaCacheManager(CacheBuilder<Object, Object> cacheBuilder, int capacity) {
23+
this(new GuavaCacheCreator(cacheBuilder), capacity);
24+
}
25+
26+
public GuavaCacheManager(CacheCreator cacheCreator) {
27+
this(cacheCreator, 16);
28+
}
29+
30+
public GuavaCacheManager(CacheCreator cacheCreator, int capacity) {
31+
super(cacheCreator, capacity);
32+
}
33+
34+
public GuavaCacheManager(Collection<Cache> caches, CacheCreator cacheCreator) {
35+
super(caches, cacheCreator);
36+
}
37+
38+
public GuavaCacheManager(Collection<Cache> caches, CacheBuilder<Object, Object> cacheBuilder) {
39+
super(caches, new GuavaCacheCreator(cacheBuilder));
40+
}
41+
42+
public GuavaCacheManager(Collection<Cache> caches) {
43+
super(caches);
44+
}
45+
}

0 commit comments

Comments
 (0)