2015-05-26 7 views
5

मेरे पास एक कस्टम CacheResolver के साथ एक स्प्रिंग बूट प्रोजेक्ट है क्योंकि मुझे रनटाइम पर फैसला करने की आवश्यकता है जिसे मैं उपयोग करना चाहता हूं, मेरे पास कोई संकलन त्रुटियां नहीं हैं, लेकिन जब मैं कुछ परीक्षण करता हूं और ब्रेक डालता हूं मेरे कस्टम CacheResolver पर इंगित करें, यह कभी भी इसमें कदम नहीं उठाता है।कस्टम कैश रीसोल्वर काम नहीं कर रहा है

यह कैश के लिए मेरे विन्यास वर्ग है:

@Component 
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.DEFAULT) 
    @CacheConfig(cacheResolver = "wgstCacheResolver") 
    public class CacheableDao<T extends Storable> extends AbstractDao<T> { 

     private final Logger logger = LoggerFactory.getLogger(CacheableDao.class); 

     public CacheableDao(final Bucket bucket, final Class<T> typeParameterClass, final DocumentType documentType) { 
     super(bucket, typeParameterClass, documentType); 
     } 

     @Cacheable(key = "{#root.methodName, #root.target.generateFullKey(#key)}") 
     public T get(final String key) throws DatastoreAccessException, ObjectMappingException { 
     //do something 
     } 
. 
. 
. 
} 

मेरे पास है:

@Configuration 
@EnableCaching(proxyTargetClass = true) 
@PropertySource(CacheConfig.CLASSPATH_DEPLOY_CACHE_PROPERTIES_PROPERTIES) 
public class CacheConfig extends CachingConfigurerSupport{ 

     public static final String CLASSPATH_DEPLOY_CACHE_PROPERTIES_PROPERTIES = "classpath:/deploy/cache-properties.properties"; 

     public static final String CACHEABLE_DOCUMENTS_PROPERTY = "cacheable.documents"; 
     public static final String TTL_CACHEABLE_DOCUMENTS_PROPERTY = "ttl.cacheable.documents"; 
     public static final String SIZED_CACHEABLE_DOCUMENTS_PROPERTY = "sized.cacheable.documents"; 
     public static final String CACHE_NAME = "permanentCache"; 
     public static final String TTL_CACHE = "ttlCache"; 
     public static final String SIZED_CACHE = "sizedCache"; 
     public static final String CACHEABLE_DOCUMENTS = "cacheableDocuments"; 
     public static final String SIZED_CACHEABLE_DOCUMENTS = "sizedCacheableDocuments"; 
     public static final int WEIGHT = 1000000; 
     public static final int TO_KBYTES = 1000; 

     @Inject 
     protected Environment environment; 

     //@Bean 
     @Override 
     public CacheManager cacheManager() { 
     SimpleCacheManager cacheManager = new SimpleCacheManager(); 
     GuavaCache sizedCache = new GuavaCache(SIZED_CACHE, CacheBuilder.newBuilder().maximumWeight(WEIGHT).weigher(
       (key, storable) -> { 
        String json = ((Storable) storable).toJson(); 
        return json.getBytes().length/TO_KBYTES; 
       } 
     ).build()); 
     GuavaCache permanentCache = new GuavaCache(CACHE_NAME,CacheBuilder.newBuilder().build()); 
     //GuavaCache ttlCache = new GuavaCache(TTL_CACHE, CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).build()); 
     cacheManager.setCaches(Arrays.asList(permanentCache,sizedCache)); 
     return cacheManager; 
     } 

     @Bean(name = "wgstCacheResolver") 
     @Override 
     public CacheResolver cacheResolver(){ 
     CacheResolver cacheResolver = new WgstCacheResolver(cacheManager(),cacheableDocuments(),sizedCacheableDocuments()); 
     return cacheResolver; 
     } 


     @Bean(name = CACHEABLE_DOCUMENTS) 
     public List<String> cacheableDocuments(){ 
     String[] cacheableDocuments = StringUtils.commaDelimitedListToStringArray(environment.getProperty(CACHEABLE_DOCUMENTS_PROPERTY)); 
     return Arrays.asList(cacheableDocuments); 
     } 

     @Bean(name = SIZED_CACHEABLE_DOCUMENTS) 
     public List<String> sizedCacheableDocuments(){ 
     String[] sizedCacheableDocuments = StringUtils.commaDelimitedListToStringArray(environment.getProperty(SIZED_CACHEABLE_DOCUMENTS_PROPERTY)); 
     return Arrays.asList(sizedCacheableDocuments); 
     } 
    } 

यहाँ मेरी CacheResolver

public class WgstCacheResolver extends AbstractCacheResolver { 

    private final List<String> cacheableDocuments; 
    private final List<String> sizedCacheableDocuments; 

    public WgstCacheResolver(final CacheManager cacheManager,final List<String> cacheableDocuments, final List<String> sizedCacheableDocuments) { 
    super(cacheManager); 
    this.cacheableDocuments = cacheableDocuments; 
    this.sizedCacheableDocuments = sizedCacheableDocuments; 
    } 

    /** 
    * Resolves the cache(s) to be updated on runtime 
    * @param context 
    * @return*/ 
    @Override 
    protected Collection<String> getCacheNames(final CacheOperationInvocationContext<?> context) { 

    final Collection<String> cacheNames = new ArrayList<>(); 
    final AbstractDao dao = (AbstractDao)context.getTarget(); 
    final String documentType = dao.getDocumentType().toString(); 
    if (cacheableDocuments.contains(documentType)){ 
     cacheNames.add("permanentCache"); 
    } 
    if (sizedCacheableDocuments.contains(documentType)){ 
     cacheNames.add("sizedCache"); 
    } 
    return cacheNames; 
    } 
} 
मेरी डीएओ

और यहाँ मैं कहाँ कैश का उपयोग करें AbstractCacheResolver को विस्तारित करने के बजाय CacheResolver को लागू करने का प्रयास किया लेकिन यह नहीं बनाया गया ई कोई अंतर।

धन्यवाद।

+0

ठीक है आपके पास कैश नाम नहीं है इसलिए यदि कैशिंग कार्य करता है, तो उसे कैश नाम को हल करना होगा अन्यथा यह अपवाद फेंक देगा। मेरा सबसे अच्छा अनुमान यह है कि कैशिंग बिल्कुल काम नहीं करती है। आपकी कॉन्फ़िगरेशन भी बहुत _weird_ है। _default_ 'कैश रेसोलवर' प्रदान करने के लिए आप 'कैशिंग कॉन्फ़िगरेशन' का उपयोग करते हैं, इसलिए आपको इसे निर्दिष्ट करने की आवश्यकता नहीं है। यदि आप इसे प्रति ऑपरेशन (विशेष नाम के साथ) निर्दिष्ट करना चाहते हैं, तो इसे कहीं और परिभाषित करें (डिफ़ॉल्ट के रूप में नहीं)। –

+0

धन्यवाद @ स्टीफन-निकोल, आपने मुझे सही दिशा में इंगित किया, मैंने 'कैशकॉन्फिग' एनोटेशन के साथ उपलब्ध कैश नामों सहित समस्या को ठीक किया, मेरे परीक्षण चलाए और डीबग किया और अब कस्टम 'कैश रेसोलवर' उम्मीद के अनुसार काम कर रहा है। मैंने माना कि कैश नामों को 'कैश रेसोलवर' के रूप में शामिल करने की आवश्यकता नहीं होगी। – tommylii

+0

आपका स्वागत है लेकिन कैश नामों की आवश्यकता नहीं है। जैसे मैंने कहा, अगर आपके कैश रिज़ॉल्वर को नहीं बुलाया गया था और आपके पास कोई अपवाद नहीं था, तो शायद आपके पास कोई कैशिंग नहीं थी। नीचे दिया गया उत्तर गलत है (जब तक कोई बग न हो) –

उत्तर

1

कैश नाम सिर्फ CacheResolver निर्दिष्ट करने के लिए पर्याप्त नहीं है, @Cacheable वर्ग उपलब्ध कैश नामों के बारे में पता करने की जरूरत है उपयोग करने के लिए, कुछ बिंदु पर शामिल किया जाना चाहिए, तो मैं उन्हें @CacheConfig एनोटेशन के साथ शामिल:

@CacheConfig(cacheNames = {WgstCacheConfig.PERMANENT_CACHE, WgstCacheConfig.SIZED_CACHE}, 
    cacheResolver = WgstCacheConfig.WGST_CACHE_RESOLVER) 
public class CacheableDao<T extends Storable> extends AbstractDao<T> { 

Caused by: java.lang.IllegalStateException: No CacheResolver specified, and no bean of type CacheManager found. Register a CacheManager bean or remove the @EnableCaching annotation from your configuration. 

तो मैं इसे इस तरह छोड़ दिया:

एक बात है कि मुझे पसंद नहीं है कि मैं, भले ही मैं इसे का उपयोग नहीं कर रहा हूँ एक अशक्त CacheManager प्रदान करने की आवश्यकता है, अन्यथा मैं निम्नलिखित त्रुटि मिलती है , ए घ यह काम करता है:

@Bean 
    public CacheManager cacheManager() { 
    return null; 
    } 

    @Bean(name = WGST_CACHE_RESOLVER) 
    public CacheResolver cacheResolver(){ 
    CacheResolver cacheResolver = new WgstCacheResolver(cacheableDocuments(),sizedCacheableDocuments(),getPermanentCache(), 
                 getSizedCache()); 
    return cacheResolver; 
    } 

मेरी परीक्षण reran, अपने कस्टम CacheResolver के माध्यम से कदम और यह सही कैश (रों)

मेरे विन्यास वर्ग CachingConfigurerSupport अब और विस्तार नहीं किया गया है करने के लिए हल करने की उम्मीद के रूप में व्यवहार किया जाता है।

+0

'WgstCacheResolver में आप एक शून्य' कैशमेनगर 'के साथ कैसे प्राप्त कर सकते हैं 'जब superclass 'AbstractCacheResolver' के पास' afterPropertiesSet' विधि 'में इसके लिए एक स्पष्ट जांच है? 'सार्वजनिक शून्य afterPropertiesSet() {' ' Assert.notNull (this.cacheManager," CacheManager रिक्त नहीं होना चाहिए ");' ' }' –

-1

कुछ और आगे के बाद (इसके बारे में क्षमा करें!) यह पता चला है कि यह वास्तव में स्प्रिंग फ्रेमवर्क में एक बग है।

मैंने SPR-13081 बनाया है। अगली रखरखाव रिलीज (4.1.7.RELEASE) के लिए एक फिक्स की अपेक्षा करें। नमूना परियोजना के लिए धन्यवाद!

+0

कोई समस्या नहीं है :) बहुत बहुत शुक्रिया में – tommylii

+0

हाय तलाश के लिए, मैं मैं प्रत्येक विधि या कक्षा पर नाम निर्दिष्ट किए बिना वैश्विक कैश को कॉन्फ़िगर करने का प्रयास कर रहा हूं। मैं समझता हूं कि एक नाम के बजाय एक कस्टम 'कैश रेसोलवर' प्रदान किया जा सकता है। दस्तावेज़ों से स्पष्ट नहीं है कि विधि/वर्ग को अभी भी एनोटेशन में इसका उल्लेख करना है या यदि आप निर्दिष्ट नहीं हैं तो क्या आप इसे टाइप करके देखते हैं? –

+0

यदि आप कस्टम कैश रिज़ॉल्यूवर निर्दिष्ट करते हैं तो हम कैश नामों को हल करने की आवश्यकता होने पर हम क्या करने जा रहे हैं। उचित कैश का समाधान कैसे किया जाता है, यह आपके कार्यान्वयन के लिए पूरी तरह से है। ऐसा कहकर, मुझे यकीन नहीं है कि मैं आपके प्रश्न या भ्रम को समझ रहा हूं जिसका आप उल्लेख कर रहे हैं। आपको अभी भी '@ कैशेबल' निश्चित रूप से निर्दिष्ट करना होगा लेकिन आपको किसी भी कैश नाम प्रदान करने की आवश्यकता नहीं है। –

संबंधित मुद्दे