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

spring boot缓存在@PostConstruct中不工作

穆乐逸
2023-03-14

我正在建立一个“类缓存”,我想稍后调用类。

主要的目标是,我不希望每次需要类实例时都扫描上下文。

# Model / Repository classes

@Getter
@RequiredArgsConstructor
public class Block implements Serializable {
    private final String className;
    private final Set<String> classCandidates = new HashSet<>();
    public boolean addCandidate(final String classCandidate) {
        return this.classCandidates.add(classCandidate);
    }
}

@Slf4j
@Component
@CacheConfig(cacheNames = ConstantsCache.CACHE_BLOCK)
public class BlockRepository {

    @Cacheable(key = "#className")
    public Block findByInputClass(final String className) {
        log.info("---> Loading classes for class '{}'", className);
        val block = new Block(className);
        findCandidates(block);
        return block;
    }
}

首先要评估缓存,我将缓存方法@AutoWired放在@RestController中,这会很好地工作。在调用rest方法时填充缓存。

@RestController
public class Controller {

    @Autowired
    BlockRepository blockRepository;

    @RequestMapping("/findByInputClass")
    public Block findByInputClass(@RequestParam("className") final String className) {
        return blockRepository.findByInputClass(className);
    }
}

完成之后,我将@AutoWired对象移动到@Service中,创建一个方法来自填充缓存。但这不起作用。调用@PostConstructor方法时不填充缓存。

@Slf4j
@Component
public class BlockCacheService {

    @Autowired
    BlockRepository blockRepository;

    @PostConstruct
    private void postConstruct() {
        log.info("*** {} PostConstruct called.", this.getClass().getTypeName());

        val block = blockRepository.findByInputClass(ConstantsGenerics.BLOCK_PARENT_CLASS);

        final Set<String> inputClasses = getInputFromCandidates(block.getClassCandidates());
        appendClassesToCache(inputClasses);
    }

    private void appendClassesToCache(final Set<String> inputClasses) {
        for (val inputClass : inputClasses) {
            blockRepository.findByInputClass(inputClass);
        }
    }
}

如何使用服务或组件正确填充缓存,这必须从应用程序开始。

提前道谢。

编辑:

我在这里找到了一个可能的解决方案:https://stackoverflow.com/a/28311225/1703546

我还更改了@service代码,以手动放置缓存,而不是使用@cacheable魔术抽象。

现在的课堂是这样的。

@Slf4j
@Component
public class BlockCacheService {

    @Autowired
    CacheManager cacheManager;

    @Autowired
    BlockRepository blockRepository;

    @PostConstruct
    private void postConstruct() {
        log.info("*** {} PostConstruct called.", this.getClass().getTypeName());

        val block = blockRepository.findByInputClass(ConstantsGenerics.BLOCK_PARENT_CLASS);

        final Set<String> inputClasses = getInputFromCandidates(block.getClassCandidates());
        appendClassesToCache(inputClasses);
    }

    private void appendClassesToCache(final Set<String> inputClasses) {
        for (val inputClass : inputClasses) {
            val block = blockRepository.findByInputClass(inputClass);
            cacheManager.getCache(ConstantsCache.CACHE_BLOCK).put(block.getClassName(), block);
        }
    }
}

现在缓存填充正确了,但问题是,这是最好的解决方案?

多谢了。

共有1个答案

翟英达
2023-03-14

您不能在@postconstruct中使用一个方面,因为它可能还没有创建(顺便说明一下)。

一种可行的方法是实现smartinitializingbean,因为它在所有单例都已完全初始化(包括它们的方面)时会给出回调。

说到这里,你的这段代码对启动时间有影响。为什么你不让你的缓存被懒洋洋地填满呢?

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

  • 我需要为我的bean类提供一些配置。在普通的Spring应用程序中,我使用@PostConstruct,但在Play 2.4中似乎不起作用

  • 我正在用 我正在使用 我已经查看了Picturefill的演示,甚至还有一个与我使用的方式非常接近的示例 有没有其他人遇到过这种情况,或者对如何修复它有什么建议?如果我使用src而不是srcset,这似乎是可行的,但我知道不建议将src与Picturefill一起使用,因为它会在不支持srcset的浏览器中导致双重下载。

  • 我正在寻找集成Hazelcast到我的应用程序... 我的要求是将所有数据加载到缓存并从缓存中提取。。 我有两个选择。 1) Hazelcast IMap 2)因为我使用的是Spring启动,所以我可以使用(@Cacheable/@CacheEvict)。 我能得到一些建议吗... 提前谢谢你。。

  • 在我的项目中,我使用了一个@Cacheable注释ia一个服务方法,它返回涉及书籍和一些标记的计算结果,我想在一个@Controller类方法中退出缓存,该方法将一本新书添加到数据库中,因为这本新书将是新计算所必需的。 服务类:@Cacheable("metas") 控制器类:@RequestMapping@CacheEvict(value=“metas”,allEntries=true)

  • 我为我的网站创建了一个AMP页面,在我的桌面浏览器上运行正常,在我的手机上测试正常,如果某些字段为空或无效,提交错误将正确显示错误消息,并且在成功提交时,它将正确显示提交成功消息。 当我将页面提交给Google缓存amp页面时,我再次测试了表单,这次它没有显示错误或成功消息。但如果表单提交有效,它将向我发送电子邮件,但不会显示成功消息。 表单html代码: PHP页面: