2013-01-07 23 views
5

Uygularken, Spring Cache Abstraction VS arabirimleriyle ilgili bir sorunla karşılaştım.Spring Cache Abstraction VS arabirimleri VS anahtar param ("Önbellek işlemi için boş değer döndü" hatası)

package com.example.cache; 

public interface IAddItMethod 
{ 
    Integer addIt(String key); 
} 

Ve iki aşağıdaki uygulamalar:

package com.example.cache; 

import org.springframework.cache.annotation.Cacheable; 
import org.springframework.stereotype.Component; 

@Component 
public class MethodImplOne implements IAddItMethod 
{ 
    @Override 
    @Cacheable(value="integersPlusOne", key="#keyOne") 
    public Integer addIt(String keyOne) 
    { 
     return new Integer(Integer.parseInt(keyOne) + 1); 
    } 
} 

aşağıdaki arayüze sahip düşünelim. IAddItMethod @Cacheable belirterek biri olmadığını

package com.example.cache; 

import org.springframework.cache.annotation.Cacheable; 
import org.springframework.stereotype.Component; 

@Component 
public class MethodImplTwo implements IAddItMethod 
{ 
    @Override 
    @Cacheable(value="integersPlusTwo", key="#keyTwo") 
    public Integer addIt(String keyTwo) 
    { 
     return new Integer(Integer.parseInt(keyTwo) + 2); 
    } 
} 

Not. @Cacheable ek açıklama olmadan başka bir uygulama (ex MethodImplThree) olabilir.

Biz basit bir beans.xml var: o ekleme

context:component-scan base-package="com.example.cache" 

, iki jUnit test durumları:

package com.example.cache; 

import static org.junit.Assert.assertEquals; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"classpath:beans.xml"}) 
public class MethodImplOneTest 
{ 

    @Autowired 
    @Qualifier("methodImplOne") 
    private IAddItMethod classUnderTest; 

    @Test 
    public void testInit() 
    { 
     int number = 1; 
     assertEquals(new Integer(number + 1), classUnderTest.addIt("" + number)); 
    } 

} 

.

package com.example.cache; 

import static org.junit.Assert.assertEquals; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"classpath:beans.xml"}) 
public class MethodImplTwoTest 
{ 

    @Autowired 
    @Qualifier("methodImplTwo") 
    private IAddItMethod classUnderTest; 

    @Test 
    public void testInit() 
    { 
     int number = 1; 
     assertEquals(new Integer(number + 2), classUnderTest.addIt("" + number)); 
    } 

} 

Testleri tek tek çalıştırdığımda başarılı olurlar. Ben onları bir arada hem çalıştırırsanız Ancak, aşağıdaki istisna ile başarısız olur, ikincisini (ille MethodImplTwoTest, sadece ikincisi koşu) (paket seçerek olarak çalıştırmak, sağ tıklama):

 
java.lang.IllegalArgumentException: Null key returned for cache operation (maybe you are using named params on classes without debug info?) CacheableOperation[public java.lang.Integer com.example.cache.MethodImplOne.addIt(java.lang.String)] caches=[integersPlusOne] | condition='' | key='#keyOne' 
    at org.springframework.cache.interceptor.CacheAspectSupport.inspectCacheables(CacheAspectSupport.java:297) 
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:198) 
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at $Proxy16.addIt(Unknown Source) 
    at com.example.cache.ITMethodImplOneIntegrationTest.testInit(ITMethodImplOneIntegrationTest.java:26) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

not: Eclipse STS 3.0 kullanıyorum ve "Oluşturulan sınıf dosyalarına değişken öznitelikleri ekle" etkin.

ÖNEMLİ: @Cacheable ek açıklamalarda "anahtarı" belirtmezsem, çalışır.

Belirttiğim herhangi bir şey var mı? yapılandırma? Ek açıklamalar?

Şimdiden teşekkürler!

cevap

4

Tahminimce, jdk proxy'si için parametre adı, ara yüz yönteminden getirilir, bu nedenle anahtar değil, anahtarAdı.

güncelleme: Sen parametre endeksleri kullanmayı deneyebilirsiniz yerine

nedense isimler (örn: yok ayıklama bilgi) mevcut değilse, parametre adları da p < altında kullanılabilir #arg> Burada #arg parametre endeksi anlamına gelir (0'dan başlayarak).

O sayesinde çalışıyor http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/cache.html#cache-spel-context

+0

bakın! Bununla birlikte, bunun kısıtlayıcı olduğunu düşünüyorum ve buna uymak için uygulamaları zorlamak karmaşık bir durumdur. Arayüze ve mevcut uygulamalara tam javadoc ekleyeceğim, ancak başka bir geliştirici yeni bir uygulama için aynı sorun üzerinde yanılabilir. Tekrar teşekkürler Boris! – dostiguy

+0

@dostiguy İndekslere göre parametrelere erişim ile ilgili belgelere bir bağlantı ekledim, ben kendim denemedim ama –

+0

İyi düşünce, bunu yapabileceğimizi unutmuştum.Denedim ve testlerimi yaptım (gerçek uygulamanın yaklaşık 100 test vakası var ve anahtarlar örneklerden daha karmaşıktır) ve işe yarıyor. Şimdi sadece hangi yolu tercih ettiğimi bilmiyorum. Tekrar teşekkürler. – dostiguy

İlgili konular