- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我想缓存主数据到Redis。
所以,我写了这些代码。
@Configuration
@EnableCaching
public class AppConfig extends CachingConfigurerSupport {
@Bean
@Autowired
public CacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
Map<String, Long> expires = new HashMap<>();
expires.put("cache.day", new Long(24 * 60 * 60));
cacheManager.setExpires(expires);
return cacheManager;
}
}
和
package com.taisho.artifacts.repository.impl;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository
public class TestRepository {
@Cacheable(value = "cache.day", key = "'cache.test'")
public List<String> getTest() {
List<String> list = new ArrayList<>();
list.add("test");
list.add("sample");
return list;
}
public void printTest() {
System.out.println(getTest());
}
}
和 ymlfile
spring:
redis:
host: 127.0.0.1
port: 26379
但是,缓存不工作...
每当我调用 printTest 方法时,“getTest”方法就会执行。Redis没有数据...我的代码有什么问题?
SpringBoot版本为1.4.0
依赖是
compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
compile("org.springframework.boot:spring-boot-starter-data-redis:${springBootVersion}")
compile("org.springframework.boot:spring-boot-autoconfigure:${springBootVersion}")
最佳答案
Spring AOP 是基于代理的,因此当您从 printTest()
方法调用 getTest()
方法时,getTest()
方法将在 this
引用上调用,而不是能够执行缓存操作的代理版本。通常这是一种设计味道,您最好重新考虑您当前的设计。但作为解决方法,您可以使用 AopContext
:
public void printTest() {
System.out.println(((TestRepository) AopContext.currentProxy()).getTest());
}
假设您有一个客户端代码可以通过依赖注入(inject)访问TestRepository
:
@Component
class SomeUnfortunateClient {
// I know field injection is evil!
@Autowired TestRepository testRepository;
void youAreGoingToBeSurprised() {
testRepository.printTest();
}
}
TestRepository
是一个 Spring 管理的存储库,为了向 TestRepository
添加额外的功能,例如缓存,Spring会为其创建一个Proxy。这意味着对 testRepository
对象引用的方法调用将是对代理的调用,因此代理将能够委托(delegate)给与该特定方法调用相关的所有拦截器(通知) .在您的情况下,这些建议将检查缓存条目是否存在。
然而,一旦调用最终到达目标对象,在本例中为 TestRepository
引用,它可能对其自身进行的任何方法调用,例如 System.out.println( getTest());
,将针对 this
引用而不是代理调用。 这意味着自调用不会导致与方法调用相关的建议有机会执行。
作为Spring Documentation状态:
Okay, so what is to be done about this? The best approach (the term best is used loosely here) is to refactor your code such that the self-invocation does not happen. For sure, this does entail some work on your part, but it is the best, least-invasive approach. The next approach is absolutely horrendous, and I am almost reticent to point it out precisely because it is so horrendous. You can (choke!) totally tie the logic within your class to Spring AOP by doing this:
public class SimplePojo implements Pojo {
public void foo() {
// this works, but... gah!
((Pojo) AopContext.currentProxy()).bar();
}
public void bar() {
// some logic...
}
}
This totally couples your code to Spring AOP, and it makes the class itself aware of the fact that it is being used in an AOP context, which flies in the face of AOP. It also requires some additional configuration when the proxy is being created.
这个答案主要基于 Spring 文档,因此对于(甚至!)更详细的讨论,您绝对应该查看 Understanding AOP proxies Spring 文档中的部分。
关于java - Spring Boot EnableCaching 和 Cacheable 注释不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41534493/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!