【发布时间】:2018-04-11 16:32:17
【问题描述】:
我正在构建一个“类缓存”,其中包含我想稍后调用的类。
主要目标是我不想每次需要类实例时都扫描上下文。
# 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://*.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);
}
}
}
现在缓存已正确填充,但问题是,这是最好的解决方案吗?
谢谢。
【问题讨论】:
标签: spring-boot concurrenthashmap spring-cache spring-boot-starter