По мере роста сложности и масштаба приложений оптимизация производительности приобретает решающее значение.
Одним из наиболее эффективных способов повышения производительности приложений является кэширование.
Аннотация @Cacheable в Spring предоставляет мощный и гибкий механизм кэширования, который может значительно повысить производительность приложения.
В этой статье рассмотрим 5 основных методов, которые должен знать каждый Java-программист при работе с @Cacheable.
1. Условное кэширование с параметром condition
Хотя базовое кэширование является простым процессом, существуют сценарии, в которых необходимо кэшировать результаты только при определенных условиях.
Параметр condition в @Cacheable позволяет определять выражения, которые должны иметь значение true, чтобы произошло кэширование.
@Service
public class ProductService {
@Cacheable(
value = "products",
condition = "#price > 1000"
)
public Product getProductDetails(String productId, double price) {
// Этот результат будет кэширован, только если цена превысит 1000
return fetchProductFromDatabase(productId);
}
}
2. Динамическая генерация ключей с помощью KeyGenerator
Стратегия генерации ключей по умолчанию может не всегда соответствовать вашим потребностям.
Пользовательские генераторы ключей позволяют создавать сложные ключи кэширования на основе множества параметров или сложной логики.
@Component
public class CustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder key = new StringBuilder();
key.append(target.getClass().getSimpleName());
key.append(method.getName());
for (Object param : params) {
key.append(param.toString());
}
return key.toString();
}
}
@Service
public class UserService {
@Cacheable(
value = "users",
keyGenerator = "customKeyGenerator"
)
public UserProfile getUserProfile(String userId, boolean includePrivateData) {
// Ключ кэша будет сгенерирован с помощью пользовательского генератора ключей
return fetchUserProfileFromDatabase(userId, includePrivateData);
}
}
3. Синхронизация кэша с помощью параметра sync
В сценариях с высокой многопоточностью несколько потоков могут пытаться загрузить одну и ту же запись в кэше одновременно.
Параметр sync помогает предотвратить проблему «давки в кэше».
@Service
public class ReportService {
@Cacheable(
value = "reports",
key = "#reportId",
sync = true
)
public Report generateReport(String reportId) {
// Только один поток будет выполнять этот метод для одного и того же reportId.
// Другие потоки будут ожидать результата.
return computeExpensiveReport(reportId);
}
}
4. Многоуровневое кэширование с несколькими именами кэша
Иногда требуется кэшировать одни и те же данные в разных кэшах с разными конфигурациями.
Параметр cacheNames позволяет указать несколько хранилищ кэша.
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
ConcurrentMapCache localCache = new ConcurrentMapCache("localCache");
RedisCache redisCache = new RedisCache("redisCache");
cacheManager.setCaches(Arrays.asList(localCache, redisCache));
return cacheManager;
}
}
@Service
public class OrderService {
@Cacheable(
cacheNames = {"localCache", "redisCache"},
key = "#orderId"
)
public Order getOrderDetails(String orderId) {
// Результат будет храниться как в локальном кэше, так и в кэше Redis
return fetchOrderFromDatabase(orderId);
}
}
5. Использование параметра unless для контроля кэша после выполнения
Параметр unless позволяет предотвратить кэширование на основе результата метода, что дает возможность более детально контролировать то, что будет кэшироваться.
@Service
public class CustomerService {
@Cacheable(
value = "customers",
key = "#customerId",
unless = "#result == null || #result.status == 'INACTIVE'"
)
public Customer getCustomerDetails(String customerId) {
Customer customer = fetchCustomerFromDatabase(customerId);
// Не будет кэшироваться, если customer является null или неактивен
return customer;
}
}
Аннотация @Cacheable — больше, чем простой механизм кэширования. Освоив эти пять методов, вы сможете реализовать сложные стратегии кэширования, которые будут эффективными и удобными в обслуживании.
Не забывайте учитывать специфику вашего случая использования при применении этих методов, поскольку разные сценарии могут требовать различных подходов.
Читайте также:
- Ключевые понятия JavaScript, которые должен знать каждый разработчик — часть 3
- Погружение в JavaScript
- 10 ключевых функций массивов JavaScript
Читайте нас в Telegram, VK и Дзен
Перевод статьи Malvin Lok: 5 Techniques You Should Know About @Cacheable as a Java Programmer





