我有一个使用 Spring Boot 2 的应用程序。我想测试一个带有@Cacheable (Spring Cache) 的方法。我做了一个简单的例子来展示这个想法:
@Service
public class KeyService {
@Cacheable("keyCache")
public String getKey() {
return "fakeKey";
}
}
Run Code Online (Sandbox Code Playgroud)
和测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
public class KeyServiceTest {
@Autowired
private KeyService keyService;
@Test
public void shouldReturnTheSameKey() {
Mockito.when(keyService.getKey()).thenReturn("key1", "key2");
String firstCall = keyService.getKey();
assertEquals("key1", firstCall);
String secondCall = keyService.getKey();
assertEquals("key1", secondCall);
}
@EnableCaching
@Configuration
static class KeyServiceConfig {
@Bean
KeyService keyService() {
return Mockito.mock(KeyService.class);
}
@Bean
CacheManager cacheManager() {
return new ConcurrentMapCacheManager("keyCache");
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的例子不起作用。但是,如果我更改getKey()
接收参数的方法: …
我有一个名为 getUserById 的方法
@Cacheable(value = "Account", key = "#accountId")
public Account getUserById(Long accountId) {
Run Code Online (Sandbox Code Playgroud)
另一个名为 getUserByIds 的方法
@Cacheable(?????)
public List<Account> getUserByIds(List<Long> accountIds) {
Run Code Online (Sandbox Code Playgroud)
如何通过帐户 ID 缓存所有帐户?谢谢
我有一个方法如下:
@Cacheable(value = "SAMPLE")
public List<SomeObj> find() {
// Method that initiates and returns the List<SomeObj> and takes around 2-3 seconds, does some logging too
}
Run Code Online (Sandbox Code Playgroud)
我正在我的配置类之一中启用缓存:
@EnableCaching
@Configuration
public SomeConf extends CachingConfigurerSupport {
// Here I also initialize my classes with @Cacheable annotation
@Bean
@Override
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Collections.singletonList((new ConcurrentMapCache("SAMPLE"))));
return cacheManager;
}
@Bean
@Override
public CacheResolver cacheResolver() {
return new SimpleCacheResolver(cacheManager());
}
@Bean
@Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
} …
Run Code Online (Sandbox Code Playgroud) 一组较旧的代码RedisCacheManager
针对RedisTemplate
产品中使用的大量缓存进行了配置。特别是模板会经常声明非字符串类型的键序列化器,例如:
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer">
<constructor-arg value="java.lang.Long"/>
</bean>
</property>
Run Code Online (Sandbox Code Playgroud)
(有时是 UUID)。当希望使用 Springboot 升级/转换到更新版本时RedisCacheManagerBuilder
,配置序列化器的唯一方法似乎是通过RedisCacheConfiguration
硬编码来获取SerializationPair<String>
for 键。
这种强制输入字符串是否有原因?
我有一个带有 Redis 缓存的 Spring Boot 2 应用程序。它工作得很好,直到我覆盖了CacheManager
bean。
问题:以下配置属性被忽略(我无法再关闭缓存):
spring.cache.type=none
Run Code Online (Sandbox Code Playgroud)
尽管根据文档它应该可以工作。
问:作品如何制作spring.cache.type=none
?
有一个像这样的解决方法,但它远不是一个好的解决方案。
更多详细信息:这是我的配置:
@Configuration
public class CacheConfiguration {
@Bean
RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory) {
return RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
}
@Bean
CacheManager cacheManager(RedisCacheWriter redisCacheWriter) {
Map<String, RedisCacheConfiguration> ttlConfiguration = ...
RedisCacheConfiguration defaultTtlConfiguration = ...
return new RedisCacheManager(
redisCacheWriter, defaultTtlConfiguration, ttlConfiguration
);
}
}
Run Code Online (Sandbox Code Playgroud) 我的 application.yml 中有一个默认的 redis 缓存配置:
cache:
type: redis
redis:
time-to-live: 7200000 # 2 hour TTL - Tune this if needed later
redis:
host: myHost
port: myPort
password: myPass
ssl: true
cluster:
nodes: clusterNodes
timeout: 10000
Run Code Online (Sandbox Code Playgroud)
它工作得很好,我不想为它创建任何自定义缓存管理器。
但是,我的代码中有一些缓存不需要使用 redis。因此,我想创建第二个 CacheManager,它是一个简单的 ConcurrentHashMap 并使用 @Cacheable 指定它
为此,我创建了一个新的 CacheManager Bean:
@Configuration
@EnableCaching
@Slf4j
class CachingConfiguration {
@Bean(name = "inMemoryCache")
public CacheManager inMemoryCache() {
SimpleCacheManager cache = new SimpleCacheManager();
cache.setCaches(Arrays.asList(new ConcurrentMapCache("CACHE"));
return cache;
}
}
Run Code Online (Sandbox Code Playgroud)
这导致 inMemoryCache 成为我的默认缓存,并且我所有其他 @Cacheable() 都尝试使用 inMemoryCache。我不希望我创建的 CacheManager bean 成为我的默认值。无论如何,我可以指定它是次要的,并且不会阻止 spring-cache …
我正在使用带有 Spring Boot 的 Hazelcast 集群缓存。我使用的是 4.2 版本的 hazelcast。
缓存工作正常,但在 TTL 后不会从缓存映射中逐出数据。始终保留相同的数据。我尝试了很多设置ttl的方法,但没有成功。
这是我的机会配置类
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.spring.cache.HazelcastCacheManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class CacheConfig {
@Value("${hazelcast.cluster-name}")
private String hzClusterName;
@Value("${hazelcast.address}")
private String hzAddress;
@Bean
HazelcastInstance hazelcastInstance() {
return HazelcastClient.newHazelcastClient(clientConfig());
}
@Bean
public ClientConfig clientConfig() {
ClientConfig cfg = ClientConfig.load();
cfg.setClusterName(hzClusterName);
cfg.getNetworkConfig().addAddress(hzAddress);
return cfg;
}
@Bean
public CacheManager cacheManager() {
return new HazelcastCacheManager(hazelcastInstance());
}
}
Run Code Online (Sandbox Code Playgroud)
我使用可缓存的缓存类
@Cacheable("items")
public String …
Run Code Online (Sandbox Code Playgroud) 我正在使用 Spring Data Cache,并使用 Redis 作为缓存管理器。配置如下:
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(
RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(SerializationPair.fromSerializer(RedisSerializer.string()))
.serializeValuesWith(SerializationPair.fromSerializer(RedisSerializer.json()))
)
.build()
Run Code Online (Sandbox Code Playgroud)
让我们想象一个使用 spring 数据缓存的非常简单的例子:
@Cacheable(...)
MyPOJO compute() { ... }
Run Code Online (Sandbox Code Playgroud)
然而,RedisSerializer.json()
确实是一个GenericJackson2JsonRedisSerializer
。因此,恕我直言,它将存储诸如{"hello":"world","@class":"com.my.name.some.package.MyPOJO"}
. 这@class: ...
部分相当长,浪费了 Redis 中宝贵的内存。此外,恕我直言,Spring Data Cache 应该足够聪明,能够意识到值类型确实是MyPOJO
,所以它不需要存储它"@class"
。
因此我的问题是:如何避免在 Spring Data Cache + Redis CacheManager 中将类名存储在序列化 JSON 中,这会浪费大量空间?
感谢您的任何建议!
谁能解释一下hibernate二级缓存和spring缓存有什么区别?
在单个应用程序中使用两者有意义吗?如果不推荐那么什么时候使用哪一个?
如果有人给出基于现实生活场景的解释,将非常有助于轻松理解。
我是缓存事物的新手,并为我的 Spring Boot 应用程序学习一些不同的解决方案。我正在研究 Spring Cache,它是比我看到的 redis 缓存更简单的缓存机制(这就是我所寻找的)。而且还有很多像“spring+redis缓存”这样的资源。当我查看简单用法时,我发现没有任何区别。即使注释是相同的(Cacheable、CacheEvict、CachePut 等),除了额外的 redis 配置和 redis docker 容器等之外,我看不到用法上的差异...而且这些spring+redis 缓存文章都没有告诉我们有什么区别介于 spring 缓存和 spring+redis 缓存之间。
redis缓存相对于spring缓存有什么优势?或者你能告诉一个简单的用例,我肯定需要使用 redis 缓存,而我无法使用 spring 缓存实现它吗?
spring-cache ×10
spring ×8
spring-boot ×8
java ×6
redis ×5
caching ×2
hazelcast ×1
hibernate ×1
mockito ×1
spring-data ×1