0

"클래스 캐시"을 빌드하고 있습니다. 나중에 클래스를 호출하려고합니다.@PostConstruct에서 스프링 부트 캐시가 작동하지 않습니다.

주요 목표은 클래스 인스턴스가 필요할 때마다 컨텍스트를 검사하고 싶지 않습니다. 캐시를 평가하는 첫 번째

# 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; 
    } 
} 

, 나는, 느릅 나무는 잘 작동하는 @RestController에서 캐시 방법을 @Autowired을 넣었습니다. 캐시는 나머지 메소드를 호출 할 때 채워집니다.

@RestController 
public class Controller { 

    @Autowired 
    BlockRepository blockRepository; 

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

가 그 일을 한 후, 내가하는 방법 생성하는 @Service@Autowired 개체 이동 한 캐시를 자기-웁니다. 그러나 이것은 효과가 없습니다. 캐시는 @ 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

@PostConstruct에서 애스펙트를 사용할 수 없습니다 (아직 is documented by the way). 그 일을 할

한 가지 방법은 모든 싱글이 완전히 초기화 된 콜백을 제공하는 대신 그들의 측면을 포함하여 (SmartInitializingBean을 구현하는 것입니다. 작업을해야 원래의 서비스에 그 변경.

가 말했다 데, 그 이 코드는 시작 시간에 영향을 미칩니다. 대신 캐시를 느리게 채우지 않도록 하시겠습니까?