当前位置: 首页 > 知识库问答 >
问题:

使用@cacheable的spring缓存不能在startup@PostConstruct上工作

窦伟
2023-03-14

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

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

结论是在@PostConstruct上调用服务方法并没有导致从数据库中缓存数据。

有没有可能先缓存数据再启动APP?我怎么能那样做?下面是我的代码片段。

@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");
    }
}

共有2个答案

西门嘉澍
2023-03-14

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

但是如果您依赖于其他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
    }
}
巫马瀚漠
2023-03-14

尝试使用applicationstartedevent而不是@postconstruct注释。

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

您应该在方法的顶部添加@EventListener(类=ApplicationStartedEvent.class)并将ApplicationStartedEvent Event作为参数传递。

示例

@EventListener(classes = ApplicationStartedEvent.class)
void init(ApplicationStartedEvent event) {
    MyObject o = service.myMethod("someString");
}
 类似资料:
  • 我正在建立一个“类缓存”,我想稍后调用类。 主要的目标是,我不希望每次需要类实例时都扫描上下文。 首先要评估缓存,我将缓存方法@AutoWired放在@RestController中,这会很好地工作。在调用rest方法时填充缓存。 完成之后,我将@AutoWired对象移动到@Service中,创建一个方法来自填充缓存。但这不起作用。调用@PostConstructor方法时不填充缓存。 如何使用

  • 问题内容: 我对此设置有问题,甚至无法查看日志。 这是我的 EJB: 的: Maven pom: 问题答案: 您具有无效的bean类型作为@DependsOn的属性。DependsOn用于表达两个Singleton会话Bean之间的依赖性,而不是Singleton和Stateless之间的依赖性。您应该将SchedulerEJB更改为Singleton或删除依赖项。 如果您决定将Scheduler

  • 当我调用我用注释的方法时,我知道缓存没有被使用,因为我在方法内部进行了打印,如果使用了缓存,就不应该打印它。 在日志中,我知道缓存正在初始化 我应该提到调用该方法的方法是常规Java

  • 目前,我正在使用Spring缓存和/注释。 我想得到某种控制台日志语句,如

  • 我正在使用SpringFramework 3.2编写一个java项目。4. 我有许多SQL查询需要缓存10秒钟。 我知道用注释我可以缓存函数结果。 我不明白的是如何缓存只有10秒。我知道你可以给可缓存注释添加条件,但是我很难弄清楚如何给这些条件添加时间。 如能提供有关该问题的任何信息,将不胜感激。