I'm on spring framework version 5.3.23, spring boot version 2.7.0
I know I can extend CachingConfigurerSupport to provide a CacheErrorHandler for handling cache layer errors. However, the interface of the bean creation is:
interface CachingConfigurer {
public CacheErrorHandler errorHandler();
}
My problem is: we need to inject some other beans into this CacheErrorHandler bean. The interface does not allow me to do that. Is there another way to configure a CacheErrorHandler bean with injection? If I simply declare a regular CacheErrorHandler bean, would it be automatically discovered by the cache configuration?
Thanks.
CodePudding user response:
No, only get CacheErrorHandler from the CachingConfigurer bean
CodePudding user response:
Well, technically, the previous answer is wrong!
In fact, you can inject other bean dependencies/collaborators into Spring Cache infrastructure components, such as a CacheErrorHandler (Javadoc) when implementing the CachingConfigurer interface (Javadoc), although maybe not in a way you might expect.
I have demonstrated your use case in this test class.
In summary:
My test configuration implements the
CachingConfigurer.I override the
errorHandler()method to return a "custom"CacheErrorHandler. Also see theTestCacheErrorHandler(custom) implementation, here.As you can see, the
TestCacheErrorHandlerrequires aLogger.The
Loggeris declared and configured as a bean in the Spring container (ApplicationContext).
NOTE: Now, you could imagine the
Loggerbeing replaced by a sophisticated management/monitoring service usingMicrometer, or perhaps a backend database. This was a test and I wanted to minimize the dependencies and complexity to focus on the problem at hand.
- In good Spring fashion, I used constructor-injection, as is recommended.
TIP: The key to this injection (autowiring), is that the bean method for the "mockLogger" bean is "proxied" by Spring (using CGLIB (class-based) proxy (as opposed to interface based proxying JDK Dynamic Proxies)). This allows the actual
mockLoggerbean to be inject and not some arbitrary object. This implicit in the@SpringBootConfigurationannotation declaration, where theproxyBeanMethodsis by default, set totrue. If I change this configuration toproxyBeanMethodsset tofalse, the test will fail, since theCacheErrorHandlerwill get a reference to an unmanagedLogger. See the Javadoc for@SpringBootConfigurationfor more details.
- The test case method goes on to assert and verify that the proper interactions happen based on the bean invocations.
NOTE: I used mock Spring Cache infrastructure components to precisely control the
Cachebehavior, such as simulating an error that would necessarily involve customCacheErrorHandlerin my test. The mock infrastructure will also allow you to test other caching infrastructure components (such as a customCacheResolver) or caching behaviors in a similar manner.
Ultimately, the test proves and demonstrates that you can inject other dependencies into caching infrastructure components, using preferably constructor injection (which is truly the only Thread-safe way to wire collaborators, especially in a multi-Threaded environment, such as a Web application, providing the this reference does not escape during construction of course ;-) ).
As 1 final test, I also tested and demonstrated that it is also possible to declare the "custom" CacheErrorHandler as a Spring "bean" managed by the Spring container and inject (autowire) additional dependencies (and here) using (field-based) setter injection (not recommended, but also possible).
The 2 key things in this test case is this and this.
If you have additional questions, please post in the comments, but I think the test class is pretty self-explanatory.
Cheers!
