从同一 bean 中自调用方法时无法识别 Spring 缓存注释

Unrecognized Spring cache annotations when self-invoking a method from within the same bean

尊敬的Spring缓存项目社区,

目前我正在使用契约第一种方法实现基于 Apache CXF 的 Spring(版本 4.1.5)Web 服务端点。在这里,我观察到在我的 Web 服务 class 中注释 public 方法时,每次我以自调用的方式调用此方法时, Spring 缓存注释“@Cachable”都会被忽略同一个豆子。当查看底层缓存提供程序(此处为:EhCache)的缓存存储库(通过 JMX)时,可以证明这一点。在那里,不会填充缓存。

查看下面的当前 Spring 文档后 Enable caching annotationsThe dispatcher servlet 我认为这可能是由于以下事实:

<cache:annotation-driven/> only looks for @Cacheable/@CachePut/@CacheEvict/@Caching on beans in the same application context it is defined in. This means that, if you put in a WebApplicationContext for a DispatcherServlet, it only checks for beans in your controllers, and not your services. See Section 17.2, “The DispatcherServlet” for more information.

目前,在 "web.xml" 部署描述符中注册的 Apache CXF "CXFServlet" 正在使用 "cxf-servlet.xml" Spring 应用程序上下文文件启动 Spring WebApplicationContext默认。 <cache:annotation-driven/> 就在那里。

或者可能是因为我从同一个 Spring bean 中调用 @Cacheable 注释方法,以便绕过生成的 Spring 代理?也可以在 Spring 文档的 "Proxy mechanisms" 章 (9.6) 中找到详细信息。

但我不知道如何更改行为以便缓存我的方法结果。你有什么想法?还是我在上面发布的假设不正确?

尊敬的 Spring 社区,

我在 Spring documentation 中找到了支持我假设的重要评论:

In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual caching at runtime even if the invoked method is marked with @Cacheable - considering using the aspectj mode in this case. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. @PostConstruct.

因此,这意味着在依赖 Spring AOP 及其代理模式技术或将模式从 "proxy" 切换到 "aspectj" <cache:annotation-driven mode="aspectj"/> 时重构代码。这允许在相同的 class 中使用自调用方法,因为 AOP 分别执行静态编织和动态编织,因此直接操作字节代码。