Spring @Cacheable,@ CachePut不适用于其他代理类

时间:2018-01-30 18:34:31

标签: java ehcache spring-cache

这是我的ProductServiceImpl类。

public class ProductServiceImpl implements ProductService {

@Autowired
 GalaxyService gs ;

@PostConstruct
private void init() {
   int hash = Objects.hash("Galaxy");
    gs.updateByName(hash);

}

@Override
@Cacheable(value = "products", key = "T(java.util.Objects).hash(#p0)")
public String getByName(String name) {
    System.out.println("Inside method");
    slowLookupOperation();
    return name + " : " + name;
}

@CacheEvict(value = "products", allEntries = true)
public void refreshAllProducts() {
    //This method will remove all 'products' from cache, say as a result of flush API.
}

public void slowLookupOperation() {
    try {
        long time = 5000L;
        Thread.sleep(time);
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
}}

这是我的GalaxyServiceImpl:

public class GalaxyServiceImpl implements GalaxyService {

@Override
@CachePut(value = "products", key = "#key")
public String updateByName(Integer key) {
    return "Oh My Galaxy- " + key;
}}

从ProductServiceImpl的init()方法,我正在更新缓存元素。看起来它是Spring缓存不缓存该方法。

但是,我是从我的Main类做的,它是缓存方法。主要课程如下:

    public mainconstructor() {

        AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        ProductService service = (ProductService) context.getBean("productService");

        GalaxyService gs = (GalaxyService) context.getBean("galaxy");


     int hash = Objects.hash("Galaxy");
     gs.updateByName(hash);

        System.out.println("Galaxy S8 ->" + service.getByName("Galaxy"));

        ((AbstractApplicationContext) context).close();
    }

我的应用程序配置类如下:

@EnableCaching
@Configuration
@ComponentScan(basePackages = {"com.websystique.spring", "com.samsung.gs8"})
public class AppConfig {

@Bean
public CacheManager cacheManager() {
    return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}

@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
    EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();
    factory.setConfigLocation(new ClassPathResource("ehcache.xml"));
    factory.setShared(true);
    factory.setAcceptExisting(false);
    return factory;
}

@Bean
public GalaxyService galaxy() {
    GalaxyService gs = new GalaxyServiceImpl();
    return gs;
}}

完成代码 - https://github.com/pijushcse/SpringCache

如果我想更新缓存项,我的问题是ProductServiceImpl有什么问题?为什么它从Main工作为什么不从其他类? TIA

2 个答案:

答案 0 :(得分:3)

快速回答是:这是正常的。您不应该在@PostConstruct中初始化缓存。

现在答案很长。 CacheInterceptor很特别。它是使用initialized = false创建的。然后,在特殊回调SmartInitializingSingleton中,它进入initialized = true。在初始化所有bean之后调用此回调。在此之前,它不会缓存任何内容。

从底线开始,您无法预先缓存@PostConstruct中的内容。

最好的解决方案是确实自己触发缓存。而且它可能更干净,它提供了更大的灵活性。所以getBean是有道理的。

答案 1 :(得分:0)

我认为您的产品服务不是缓存,但Galaxy是。您无法调用slowOperation并将其缓存在同一个类中。缓存impls。应该包装需要缓存的内容。提取包含慢速操作调用的缓存服务。