Skip to content
Back to skills

118 Cache Core Reference 1b795999

ASecurity

Complete API reference and external resources for Spring Boot caching.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
documentationjavaexpressspringtestinggitapidatabaseperformancedocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 118-cache-core-reference_1b795999 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 118 Cache Core Reference 1b795999?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 118 Cache Core Reference 1b795999
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-118-cache-core-reference-1b795999/badge)](https://www.skillsdirectory.com/skills/tools-only-118-cache-core-reference-1b795999)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Spring Boot Cache Abstraction - References

Complete API reference and external resources for Spring Boot caching.

## Spring Cache Abstraction API Reference

### Core Interfaces

#### CacheManager
Interface for managing cache instances.

```java
public interface CacheManager {
    // Get a cache by name
    Cache getCache(String name);
    
    // Get all available cache names
    Collection<String> getCacheNames();
}
```

**Common Implementations:**
- `ConcurrentMapCacheManager` - In-memory, thread-safe caching
- `SimpleCacheManager` - Simple static cache configuration
- `CaffeineCacheManager` - High-performance caching with Caffeine library
- `EhCacheManager` - Enterprise caching with EhCache
- `RedisCacheManager` - Distributed caching with Redis

#### Cache
Interface representing a single cache.

```java
public interface Cache {
    // Get cache name
    String getName();
    
    // Get native cache implementation
    Object getNativeCache();
    
    // Get value by key
    ValueWrapper get(Object key);
    
    // Put value in cache
    void put(Object key, Object value);
    
    // Remove entry from cache
    void evict(Object key);
    
    // Clear entire cache
    void clear();
}
```

### Cache Annotations

| Annotation | Purpose | Target | Parameters |
|-----------|---------|--------|-----------|
| `@Cacheable` | Cache method result before execution | Methods | `value`, `key`, `condition`, `unless` |
| `@CachePut` | Always execute, then cache result | Methods | `value`, `key`, `condition`, `unless` |
| `@CacheEvict` | Remove entry/entries from cache | Methods | `value`, `key`, `allEntries`, `condition`, `beforeInvocation` |
| `@Caching` | Combine multiple cache operations | Methods | `cacheable`, `put`, `evict` |
| `@CacheConfig` | Class-level cache configuration | Classes | `cacheNames` |
| `@EnableCaching` | Enable caching support | Configuration classes | None |

### Annotation Parameters

#### value / cacheNames
Name(s) of the cache(s) to use.

```java
@Cacheable(value = "products")  // Single cache
@Cacheable(value = {"products", "inventory"})  // Multiple caches
```

#### key
SpEL expression to generate cache key (if not using method parameters as key).

```java
@Cacheable(value = "products", key = "#id")
@Cacheable(value = "products", key = "#p0")  // First parameter
@Cacheable(value = "products", key = "#root.methodName + #id")
@Cacheable(value = "products", key = "T(java.util.Objects).hash(#id, #name)")
```

**SpEL Context Variables:**
- `#root.methodName` - Method name being invoked
- `#root.method` - Method object
- `#root.target` - Target object
- `#root.targetClass` - Target class
- `#root.args[0]` - Method arguments array
- `#a0`, `#p0` - First argument
- `#result` - Method result (only in @CachePut, @CacheEvict)

#### condition
SpEL expression evaluated before cache operation. Operation only executes if true.

```java
@Cacheable(value = "products", condition = "#id > 0")
@Cacheable(value = "products", condition = "#price > 100 && #active == true")
@Cacheable(value = "products", condition = "#size() > 0")  // For collections
```

#### unless
SpEL expression evaluated AFTER method execution. Entry is cached only if false.

```java
@Cacheable(value = "products", unless = "#result == null")
@CachePut(value = "products", unless = "#result.isPrivate()")
```

#### beforeInvocation
For @CacheEvict only. If true, cache is evicted BEFORE method execution (default: false).

```java
@CacheEvict(value = "products", beforeInvocation = true)  // Evict before call
@CacheEvict(value = "products", beforeInvocation = false)  // Evict after call
```

#### allEntries
For @CacheEvict only. If true, entire cache is cleared instead of single entry.

```java
@CacheEvict(value = "products", allEntries = true)  // Clear all entries
```

## Configuration Reference

### Maven Dependencies

```xml
<!-- Spring Cache Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>3.5.6</version>
</dependency>

<!-- Caffeine (Optional, for advanced caching) -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.6</version>
</dependency>

<!-- EhCache (Optional, for distributed caching) -->
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.10.8</version>
    <classifier>jakarta</classifier>
</dependency>

<!-- Redis (Optional, for distributed caching) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>3.5.6</version>
</dependency>
```

### Gradle Dependencies

```gradle
dependencies {
    // Spring Cache Starter
    implementation 'org.springframework.boot:spring-boot-starter-cache:3.5.6'

    // Caffeine
    implementation 'com.github.ben-manes.caffeine:caffeine:3.1.6'

    // EhCache
    implementation 'javax.cache:cache-api:1.1.1'
    implementation 'org.ehcache:ehcache:3.10.8'

    // Redis
    implementation 'org.springframework.boot:spring-boot-starter-data-redis:3.5.6'
}
```

### Application Properties (application.properties)

```properties
# General Caching Configuration
spring.cache.type=simple  # Type: simple, redis, caffeine, ehcache, jcache

# Caffeine Configuration
spring.cache.caffeine.spec=maximumSize=1000,expireAfterWrite=10m
spring.cache.cache-names=products,users,orders

# Redis Configuration
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password=
spring.cache.redis.time-to-live=600000  # 10 minutes in ms

# EhCache Configuration
spring.cache.jcache.config=classpath:ehcache.xml
```

### Application Properties (application.yml)

```yaml
spring:
  cache:
    type: simple
    cache-names:
      - products
      - users
      - orders
    
    caffeine:
      spec: maximumSize=1000,expireAfterWrite=10m
    
    redis:
      time-to-live: 600000  # 10 minutes in ms
    
    jcache:
      config: classpath:ehcache.xml
```

## Performance Tuning Reference

### Cache Types Comparison

| Type | Use Case | Memory | Thread-Safe | Distributed |
|------|----------|--------|------------|-------------|
| Simple | Local, small data | Low | Yes | No |
| Caffeine | High-performance local | Medium | Yes | No |
| EhCache | Enterprise local | High | Yes | Optional |
| Redis | Distributed, large | External | Yes | Yes |

### Performance Tips

**1. Key Generation Strategy:**
```java
// Fast (uses method parameters directly)
@Cacheable(value = "products")  // Uses all parameters as key
@Cacheable(value = "products", key = "#id")  // Specific parameter

// Slower (computed SpEL)
@Cacheable(value = "products", key = "T(java.util.Objects).hash(#id, #name)")
```

**2. Cache Size Tuning:**
```properties
# Caffeine: Set appropriate maximumSize
spring.cache.caffeine.spec=maximumSize=10000,expireAfterWrite=15m

# Redis: Monitor memory usage
# MEMORY STATS command in Redis CLI
```

**3. TTL Configuration:**
```properties
# Redis: TTL in milliseconds
spring.cache.redis.time-to-live=600000  # 10 minutes

# Caffeine: In spec
spring.cache.caffeine.spec=expireAfterWrite=10m
```

## Spring Boot Auto-Configuration

### Auto-Detected Cache Managers

Spring Boot auto-configures a CacheManager based on classpath presence (in priority order):

1. **Redis** - if `spring-boot-starter-data-redis` is present
2. **Caffeine** - if `caffeine` library is present
3. **EhCache** - if `ehcache` library is present
4. **Simple** - default in-memory caching

To explicitly set the cache type:
```properties
spring.cache.type=redis
```

### Conditional Bean Creation

```java
@Bean
@ConditionalOnMissingBean(CacheManager.class)
public CacheManager cacheManager() {
    return new ConcurrentMapCacheManager("products", "users");
}
```

## Transaction Integration

### Cache + @Transactional Interaction

```java
@Service
@Transactional
public class ProductService {
    
    @Cacheable(value = "products", key = "#id")
    @Transactional(readOnly = true)  // Combines with cache
    public Product getProduct(Long id) {
        return productRepository.findById(id).orElse(null);
    }
    
    @CachePut(value = "products", key = "#product.id")
    @Transactional  // Ensure atomicity of save + cache update
    public Product updateProduct(Product product) {
        return productRepository.save(product);
    }
    
    @CacheEvict(value = "products", key = "#id")
    @Transactional
    public void deleteProduct(Long id) {
        productRepository.deleteById(id);
    }
}
```

## Monitoring and Metrics

### Spring Boot Actuator Integration

```properties
# Enable caching metrics
management.endpoints.web.exposure.include=metrics,health

# View cache metrics
GET http://localhost:8080/actuator/metrics
GET http://localhost:8080/actuator/metrics/cache.hits
GET http://localhost:8080/actuator/metrics/cache.misses
```

### Custom Cache Metrics

```java
@Component
public class CacheMetricsCollector {
    private final MeterRegistry meterRegistry;

    public void recordCacheHit(String cacheName) {
        meterRegistry.counter("cache.hits", "cache", cacheName).increment();
    }

    public void recordCacheMiss(String cacheName) {
        meterRegistry.counter("cache.misses", "cache", cacheName).increment();
    }
}
```

## EhCache XML Configuration Reference

### ehcache.xml Structure

```xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.ehcache.org/v3"
    xmlns:jsr107="http://www.ehcache.org/v3/jsr107"
    xsi:schemaLocation="
        http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
        http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

    <!-- Cache Configuration -->
    <cache alias="cacheName">
        <key-type>java.lang.Long</key-type>
        <value-type>com.example.Product</value-type>
        
        <!-- Time to Live -->
        <expiry>
            <ttl unit="minutes">30</ttl>
        </expiry>
        
        <!-- Storage Configuration -->
        <resources>
            <heap unit="entries">1000</heap>
            <offheap unit="MB">50</offheap>
            <disk unit="GB">1</disk>
        </resources>
        
        <!-- Listeners (optional) -->
        <listeners>
            <listener>
                <class>com.example.CustomCacheEventListener</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
            </listener>
        </listeners>
    </cache>
</config>
```

### Common EhCache Attributes

- `heap` - On-heap memory storage (fast, limited)
- `offheap` - Off-heap memory storage (slower, larger)
- `disk` - Disk storage (slowest, unlimited)
- `ttl` - Time to live before expiration
- `idle` - Time to idle before expiration (if not accessed)

## Common Pitfalls and Solutions

### Problem 1: Cache Not Working

**Symptoms:** Cache is never hit, always querying database.

**Causes & Solutions:**
```java
// Problem: @Cacheable on public method called from same bean
@Service
public class ProductService {
    @Cacheable("products")
    public Product get(Long id) { }
    
    public Product getDetails(Long id) {
        return this.get(id);  // ❌ Won't use cache (no proxy)
    }
}

// Solution: Inject service or call through interface
@Service
public class DetailsService {
    @Autowired
    private ProductService productService;
    
    public Product getDetails(Long id) {
        return productService.get(id);  // ✅ Uses cache
    }
}

// Problem: Caching non-serializable objects with Redis
@Cacheable("products")
public Product get(Long id) {
    Product p = new Product();
    p.setConnection(dbConnection);  // ❌ Not serializable
    return p;
}

// Solution: Ensure all cached objects are serializable
@Cacheable("products")
public ProductDTO get(Long id) {
    return mapper.toDTO(productRepository.findById(id));  // ✅ DTO is serializable
}
```

### Problem 2: Stale Cache Data

**Symptoms:** Updates aren't reflected in cached data.

**Solution:**
```java
// Always evict cache on update
@CacheEvict(value = "products", key = "#id")
public void updateProduct(Long id, UpdateRequest req) {
    Product product = productRepository.findById(id).orElseThrow();
    product.update(req);
    productRepository.save(product);
}

// Or use @CachePut to keep cache fresh
@CachePut(value = "products", key = "#result.id")
public Product updateProduct(Long id, UpdateRequest req) {
    Product product = productRepository.findById(id).orElseThrow();
    product.update(req);
    return productRepository.save(product);
}
```

### Problem 3: Memory Leak

**Symptoms:** Memory usage grows unbounded.

**Solution:**
```properties
# Configure cache eviction policies
spring.cache.caffeine.spec=maximumSize=10000,expireAfterWrite=10m

# Redis: Set TTL
spring.cache.redis.time-to-live=600000

# Monitor cache size
```

## External Resources

### Official Documentation

- [Spring Cache Abstraction](https://docs.spring.io/spring-framework/reference/integration/cache.html)
- [Spring Boot Caching Documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.caching)
- [Spring Framework Caching Guide](https://spring.io/guides/gs/caching/)

### Third-Party Libraries

- [Caffeine Cache](https://github.com/ben-manes/caffeine/wiki)
- [EhCache Documentation](https://www.ehcache.org/documentation/3.10/)
- [Redis Documentation](https://redis.io/documentation)

### Related Skills

- **spring-boot-performance-tuning** - Comprehensive performance optimization
- **spring-boot-data-persistence** - Database optimization patterns
- **spring-boot-rest-api-standards** - API design with caching headers

### Useful Articles

- [Spring Cache Abstraction Tutorial](https://www.baeldung.com/spring-cache-tutorial)
- [Redis Caching in Spring Boot](https://www.baeldung.com/spring-boot-redis)
- [Cache Stampede Problem](https://en.wikipedia.org/wiki/Cache_stampede)
- [Cache Invalidation Strategies](https://martinfowler.com/bliki/TwoHardThings.html)

## SpEL Reference for Cache Keys

### Basic Expressions

```java
// Method parameters
@Cacheable(key = "#id")           // Single parameter
@Cacheable(key = "#user.id")      // Object property
@Cacheable(key = "#root.args[0]") // First argument

// Composite keys
@Cacheable(key = "#id + '-' + #type")
@Cacheable(key = "T(java.util.Objects).hash(#id, #type)")

// Collections
@Cacheable(key = "#ids.toString()")
@Cacheable(condition = "#ids.size() > 0")
```

### SpEL Context Variables

| Variable | Description |
|----------|-------------|
| `#root.method` | Method object |
| `#root.methodName` | Method name |
| `#root.target` | Target object |
| `#root.targetClass` | Target class |
| `#root.args` | Arguments array |
| `#p<index>` | Argument at index |
| `#<name>` | Named argument |
| `#result` | Method result (@CachePut, @CacheEvict) |

## Testing Reference

### Testing Cache Behavior

```java
@Test
void shouldCacheResult() {
    // Arrange
    when(repository.find(1L)).thenReturn(mockObject);
    
    // Act - First call
    service.get(1L);
    
    // Assert - Database was queried
    verify(repository, times(1)).find(1L);
    
    // Act - Second call
    service.get(1L);
    
    // Assert - Database NOT queried again (cache hit)
    verify(repository, times(1)).find(1L);
}
```

### Disabling Cache in Tests

```java
@SpringBootTest
@PropertySource("classpath:application-test.properties")
class MyServiceTest {
    // In application-test.properties:
    // spring.cache.type=none
}
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.