文档说:
自调用
只有通过代理传入的外部方法调用才会被拦截。这意味着自调用,实际上是目标对象中的一个方法调用目标对象的另一个方法,即使调用的方法被标记为@Cacheable,在运行时也不会导致实际的缓存拦截。
顺便说一句,我不得不调整你的测试项目以满足 sbt。
这是用于比较的两个堆栈跟踪(低于规范2)。
外部拦截:
at com.github.fommil.cache.Thingy.expensive(Thingy.scala:20)
at com.github.fommil.cache.Thingy$$FastClassByCGLIB$$f58b1afb.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at com.googlecode.ehcache.annotations.resolver.ThreadLocalCacheEntryFactory.createEntry(ThreadLocalCacheEntryFactory.java:36)
at net.sf.ehcache.constructs.blocking.SelfPopulatingCache.get(SelfPopulatingCache.java:73)
at net.sf.ehcache.constructs.blocking.BlockingCache.get(BlockingCache.java:243)
at com.googlecode.ehcache.annotations.interceptor.EhCacheInterceptor.invokeSelfPopulatingCacheable(EhCacheInterceptor.java:174)
at com.googlecode.ehcache.annotations.interceptor.EhCacheInterceptor.invokeCacheable(EhCacheInterceptor.java:122)
at com.googlecode.ehcache.annotations.interceptor.EhCacheInterceptor.invoke(EhCacheInterceptor.java:81)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.github.fommil.cache.Thingy$$EnhancerByCGLIB$$d7d992e.expensive(<generated>)
at com.github.fommil.cache.Thingy$$FastClassByCGLIB$$f58b1afb.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:132)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.github.fommil.cache.Thingy$$EnhancerByCGLIB$$c2c26afd.expensive(<generated>)
at com.github.fommil.cache.ThingySpec$$anonfun$1$$anonfun$apply$5.apply(ThingySpec.scala:16)
at com.github.fommil.cache.ThingySpec$$anonfun$1$$anonfun$apply$5.apply(ThingySpec.scala:15)
...并在内部调用:
at com.github.fommil.cache.Thingy.expensive(Thingy.scala:20)
at com.github.fommil.cache.Thingy.internallyCalling(Thingy.scala:24)
at com.github.fommil.cache.Thingy$$FastClassByCGLIB$$f58b1afb.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:627)
at com.github.fommil.cache.Thingy$$EnhancerByCGLIB$$d7d992e.internallyCalling(<generated>)
at com.github.fommil.cache.Thingy$$FastClassByCGLIB$$f58b1afb.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:132)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.github.fommil.cache.Thingy$$EnhancerByCGLIB$$c2c26afd.internallyCalling(<generated>)
at com.github.fommil.cache.ThingySpec$$anonfun$1$$anonfun$apply$6.apply(ThingySpec.scala:22)
at com.github.fommil.cache.ThingySpec$$anonfun$1$$anonfun$apply$6.apply(ThingySpec.scala:21)
毫不奇怪,类似以下的工作:
import org.springframework.beans.factory.{ BeanFactory, BeanFactoryAware }
@Service
@Scope(proxyMode = TARGET_CLASS)
class Thingy extends JavaLogging with BeanFactoryAware {
var called = 0
@Cacheable(cacheName = "thingy", decoratedCacheType = SELF_POPULATING_CACHE)
def expensive() = {
called += 1
Thread.sleep(1000)
new Throwable().printStackTrace()
"bob"
}
var myProxy: Thingy = _
var myFactory: BeanFactory = _
def setBeanFactory(beanFactory: BeanFactory): Unit = {
myFactory = beanFactory
}
def internallyCalling() = {
if (myProxy == null) myProxy = myFactory getBean classOf[Thingy]
myProxy.expensive()
}
}
只是为了确保没有本地检测正在进行,这可能取决于调用堆栈而被禁用,我通过调用伴随对象并返回来尝试它,并在将来包装它,但神奇的是代理.