2017-01-18 25 views
0

次のクラスとインターフェイスを使用しています(簡潔にするために簡略化されています)。デプロイ完了前にキャッシング可能なキャッシングアノテーションが機能しない

@Serivce 
class Service1 { 

    @Cacheable("cacheName") 
    public Metadata preLoadMetadata() { 
     // load data from database 
    } 
} 

@Service 
class Service2 implements Loader { 

    @Autowired @Lazy 
    private Service1 service1; 

    @Overrride 
    public CacheWrapper getCacheWrapper() { 
     return new CacheWrapper(() -> service1.preLoadMetadata()); 
    } 
} 

interface Loader { 
    CacheWrapper getCacheWrapper(); 
} 

class CacheWrapper { 

    private Callable callable; 

    public CacheWrapper(Callable callable) { 
     this.callable = callable; 
    } 

    public getCallable() { 
     return callable; 
    } 
} 

デプロイ時にキャッシュをロードするためのSpring Bean。

@Component 
class LoadCache { 

    @Autowired 
    private List<Loader> allLoaders; 

    @PostConstruct 
    public void load() { 
     allLoaders.getCacheWrapper().getCallable().call(); 
    } 
} 

preLoadMetadata()キャッシュにデータを保存せずに実行します。デプロイメントが完了し、同じメソッドpreLoadMetadata()を呼び出した後、データをキャッシュに保存します。

なぜ@Cacheableは展開時に機能しませんか?

@PostConstructと注釈されたメソッド内に手動でputメソッドCacheを使用してキャッシュすると、展開中に正常に実行できます。

私はサーバーとしてTomcatを使用しています。
私はSpringキャッシュ抽象化の背後にあるCouchbaseキャッシュを使用しています。

+0

導入の途中です。 – Kayaman

+0

@ Kayamanもしそうなら、なぜそれがプログラムでキャッシュにデータを埋め込むのですか? – rohanagarwal

答えて

0

Cacheable注釈機能していないため、根本的な原因: afterSingletonsInstantiated()方法はinitializedフラグを設定しますBeanFactoryがすべてのBeanをインスタンス化した場合にのみtrueになります。 initializedフラグがfalseの場合、キャッシング操作は実行されません。ここで、post構造体の内部で、プリロードキャッシュを開始すると、LoadCacheがインスタンス化される最後のBeanではない可能性が高くなります。したがって、キャッシング操作は実行されません(キャッシング注釈を使用している間)。

したがって、ContextRefreshEventに応答する注釈は、コンテキストが開始され、次にキャッシュのロードのみが行われることを保証するこの場合に最も適したものです。

1

あなたのキャッシュをプリロードしたい場合は、私はあなたがあなたのアプリケーションが起動した後に実行されますApplicationListenerを使用することをお勧め:

@Component 
public class CacheInitializer implements ApplicationListener<ContextRefreshedEvent>{ 

    @Autowired 
    private List<Loader> allLoaders; 

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent event) { 
     allLoaders.getCacheWrapper().getCallable().call(); 
    } 
} 
+0

私はあなたのApplicationListenerの使用が好きです。しかし、なぜあなたはCacheableがうまくいかないのかについて何かを投げることができますか? cacheManagerはインスタンス化され、すべてのキャッシュは準備ができていますが、Cacheableは機能しません。 – rohanagarwal

+0

Beanはまだ初期化フェーズにあるので、aspectjのアスペクトはまだ有効になっていない可能性があります。 – codependent

+0

@EventListener(value = "ContextRefreshedEvent.class")アノテーションを使用することで、ApplicationListenerの実装を妨げることもあります。 – rohanagarwal