Spring Boot迁移后JCacheManagerCustomizer的customize方法失效问题
Hey there, let's tackle this frustrating JCache customization issue you're hitting after upgrading to Spring Boot 2. I've dealt with similar problems in the past, so here's a breakdown of what's likely going wrong and how to fix it:
1. Spring Boot 2's JCache Auto-Configuration Changes
Spring Boot 2 overhauled some cache auto-config logic, and your existing @AutoConfigureBefore ordering might no longer be sufficient to ensure your customizations run before Hibernate initializes its cache.
First, adjust your configuration class to prioritize loading before Hibernate's database-related config explicitly:
@Configuration @EnableCaching // Swap the order to ensure cache config loads before database/Hibernate setup @AutoConfigureBefore(value = {DatabaseConfiguration.class, WebConfigurer.class}) public class CacheConfiguration { private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class); @Bean public JCacheManagerCustomizer cacheManagerCustomizer() { return cacheManager -> { log.info("Executing JCache manager customization..."); // Add this log to verify execution // Your existing customization logic here, e.g.: MutableConfiguration<Object, Object> defaultConfig = new MutableConfiguration<>() .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ofMinutes(15))) .setStoreByValue(false) .setStatisticsEnabled(true); // Configure Hibernate's internal caches cacheManager.createCache("org.hibernate.cache.internal.StandardQueryCache", defaultConfig); cacheManager.createCache("org.hibernate.cache.spi.UpdateTimestampsCache", defaultConfig); // Add your entity-specific cache regions cacheManager.createCache("com.yourpackage.YourEntity", defaultConfig); }; } }
2. Force Hibernate to Use Spring-Managed CacheManager
A common pitfall in Spring Boot 2 is that Hibernate might create its own JCache Manager instead of using the one you customized. Fix this by explicitly binding your Spring CacheManager to Hibernate:
Add this bean to your CacheConfiguration:
@Bean public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(CacheManager cacheManager) { return properties -> properties.put("hibernate.javax.cache.cache_manager", cacheManager); }
3. Verify Application Properties
Double-check your application.properties (or .yml) to ensure Hibernate is configured to use JCache correctly:
# Cache type spring.cache.type=jcache # Hibernate second-level cache settings spring.jpa.properties.hibernate.cache.use_second_level_cache=true spring.jpa.properties.hibernate.cache.use_query_cache=true spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.jcache.JCacheRegionFactory # Optional: If you're using a JCache config file (e.g. Ehcache 3) # spring.cache.jcache.config=classpath:ehcache.xml
4. Validate Dependencies
Make sure you have all required JCache/Hibernate dependencies in your pom.xml (or build.gradle):
<dependencies> <!-- Spring Cache starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!-- Hibernate JCache integration --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jcache</artifactId> </dependency> <!-- JCache implementation (e.g. Ehcache 3) --> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency> </dependencies>
5. Debug the Load Order
Enable debug logging for Spring's cache and Hibernate modules to confirm your customizer runs before Hibernate initializes its cache. Add these log settings to your application.properties:
logging.level.org.springframework.cache=DEBUG logging.level.org.hibernate.cache=DEBUG
Look for logs like Executing JCache manager customization... (from your customizer) appearing before Hibernate's cache initialization logs.
内容的提问来源于stack exchange,提问作者ali akbar azizkhani

