我正在构建一个"类缓存" ,我希望稍后调用它们。
主要目标是每次需要类实例时我都不想扫描上下文。
# 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);
}
}
}
现在缓存已正确填充,但问题是,这是最好的解决方案吗?
感谢。
答案 0 :(得分:0)
您无法使用@PostConstruct
中的某个方面,因为它可能尚未创建(以及is documented by the way)。
实现这项工作的一种可能方法是实现SmartInitializingBean
,因为当所有单例都已完全初始化时(包括它们的方面),它会给出回调。更改原始服务上的内容应该有效。
话虽如此,您的此代码会对启动时间产生影响。为什么不让你的缓存懒散地填充?