Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用@Cacheable的Spring缓存在启动@PostConstruct时不工作_Java_Spring_Caching_Spring Cache - Fatal编程技术网

Java 使用@Cacheable的Spring缓存在启动@PostConstruct时不工作

Java 使用@Cacheable的Spring缓存在启动@PostConstruct时不工作,java,spring,caching,spring-cache,Java,Spring,Caching,Spring Cache,我正在使用Spring,我想在启动应用程序之前缓存一些数据 我在其他帖子中找到了一些解决方案,使用@PostConstruct调用我的@Service方法(注释为@Cacheable),例如。 我这样做了,但在应用程序启动后,我调用REST端点,该端点再次调用此服务方法,它在另一次发送数据库请求(所以它还没有被缓存)。当我向端点发送第二次缓存数据的请求时 结论是,在@PostConstruct上调用服务方法不会导致缓存数据库中的数据 是否可以在启动应用程序之前缓存数据?我该怎么做?下面是我的代码

我正在使用Spring,我想在启动应用程序之前缓存一些数据

我在其他帖子中找到了一些解决方案,使用@PostConstruct调用我的@Service方法(注释为@Cacheable),例如。 我这样做了,但在应用程序启动后,我调用REST端点,该端点再次调用此服务方法,它在另一次发送数据库请求(所以它还没有被缓存)。当我向端点发送第二次缓存数据的请求时

结论是,在@PostConstruct上调用服务方法不会导致缓存数据库中的数据

是否可以在启动应用程序之前缓存数据?我该怎么做?下面是我的代码片段

@RestController
class MyController {

    private static final Logger logger = LoggerFactory.getLogger(MyController.class);

    @Autowired
    MyService service;

    @PostConstruct
    void init() {
        logger.debug("MyController @PostConstruct started");
        MyObject o = service.myMethod("someString");
        logger.debug("@PostConstruct: " + o);
    }

    @GetMapping(value = "api/{param}")
    MyObject myEndpoint(@PathVariable String param) {
        return service.myMethod(param);
    }

}


@Service
@CacheConfig(cacheNames = "myCache")
class MyServiceImpl implements MyService {

    @Autowired
    MyDAO dao;

    @Cacheable(key = "{ #param }")
    @Override
    public MyObject myMethod(String param) {
        return dao.findByParam(param);
    }
}


interface MyService {
    MyObject myMethod(String param);
}


@Repository
interface MyDAO extends JpaRepository<MyObject, Long> {
    MyObject findByParam(String param);
}


@SpringBootApplication
@EnableConfigurationProperties
@EnableCaching
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Primary
    @Bean
    public CacheManager jdkCacheManager() {
        return new ConcurrentMapCacheManager("myCache");
    }
}
@RestController
类MyController{
私有静态最终记录器Logger=LoggerFactory.getLogger(MyController.class);
@自动连线
我的服务;
@施工后
void init(){
调试(“MyController@PostConstruct启动”);
MyObject o=service.myMethod(“someString”);
logger.debug(“@PostConstruct:+o”);
}
@GetMapping(value=“api/{param}”)
MyObject myEndpoint(@PathVariable字符串参数){
返回服务.myMethod(param);
}
}
@服务
@CacheConfig(cacheNames=“myCache”)
类MyServiceImpl实现MyService{
@自动连线
MyDAO道;
@可缓存(key=“{#param}”)
@凌驾
公共MyObject myMethod(字符串参数){
返回dao.findByParam(param);
}
}
接口MyService{
MyObject myMethod(字符串参数);
}
@存储库
接口MyDAO扩展了JpaRepository{
MyObject findByParam(字符串参数);
}
@SpringBoot应用程序
@EnableConfigurationProperties
@启用缓存
公共类MyApplication{
公共静态void main(字符串[]args){
run(MyApplication.class,args);
}
@初级的
@豆子
公共缓存管理器jdkCacheManager(){
返回新的ConcurrentMapCacheManager(“myCache”);
}
}

@PostConstruct适用于您的情况。在实例化方法bean之后,将调用带有@PostConstruct注释的方法

但是,如果您依赖于其他bean,并且在应用程序上下文完全启动后调用了您的方法,您会这样做吗?您可以创建一个新bean,如下所示:

@Component
public class MyListener 
        implements ApplicationListener<ContextRefreshedEvent> {

    public void onApplicationEvent(ContextRefreshedEvent event) {
        //Here call your method of cache
        // Your methode will be called after the application context has fully started
    }
}
@组件
公共类MyListener
实现ApplicationListener{
ApplicationEvent(ContextRefreshedEvent事件)上的公共无效{
//这里调用缓存的方法
//应用程序上下文完全启动后,将调用methode
}
}

尝试使用
应用程序启动事件
而不是
@PostConstruct
注释

我也有同样的问题,这个小零钱就解决了

你应该加上
@EventListener(classes=ApplicationStartedEvent.class)
在你的方法和通行证之上
ApplicationStartedEvent事件
作为一个参数

例如:

@EventListener(classes = ApplicationStartedEvent.class)
void init(ApplicationStartedEvent event) {
    MyObject o = service.myMethod("someString");
}

@PostConstruct
中尝试这样做通常是一个坏主意,它可能会提前运行(没有创建代理,因此没有应用AOP)。最好在侦听
ContextRefreshedEvent
s的
ApplicationListener中执行类似操作。这是一个触发器,告诉您一切都已启动,您现在可以调用缓存方法。@M.Deinum ok,但我需要在REST端点启动和侦听请求之前启动缓存。我该怎么做?调度员服务一启动,它就开始监听。。。如上所述,使用
ApplicationListener
以获得安全的方式。@M.Deinum谢谢,这解决了我的问题!