Варианты ответа:
Anonymous Quiz
64%
Final counter: 6
9%
Final counter: 5
9%
Final counter: 4
18%
Final counter: 3
Аннотации @Cacheable и @CacheEvict
@Cacheable
Аннотация @Cacheable указывает, что результат метода должен быть сохранён в кеше. Если метод вызывается с теми же аргументами, то возвращается кешированное значение, а не выполняется метод.
Параметры
value / cacheNames (обязательный параметр)
Имя кеша, в который сохраняется результат. Можно указать одно или несколько значений.
```
@Cacheable("usersCache")
```
key (опциональный)
Позволяет задать ключ для кеша. Если не указано, ключ формируется автоматически на основе аргументов метода.
Можно использовать SpEL (Spring Expression Language) для создания ключей.
```
@Cacheable(value = "usersCache", key = "#id")
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
```
condition (опциональный)
Условие, при котором результат метода будет закеширован. Используется SpEL. Если условие не выполнено, кеширование не происходит.
unless (опциональный)
Условие, при котором результат НЕ будет кешироваться, даже если метод выполнен. Отличается от condition, так как проверяется после выполнения метода.
sync (опциональный)
Если true, запросы для одного и того же ключа будут синхронизированы, чтобы предотвратить одновременное выполнение метода для одного ключа.
Пример использования
1. Простое кеширование
Кеширование результата метода:
2. Сложный ключ для кеша
3. Использование условий
#Java #Training #Spring #Cacheable
@Cacheable
Аннотация @Cacheable указывает, что результат метода должен быть сохранён в кеше. Если метод вызывается с теми же аргументами, то возвращается кешированное значение, а не выполняется метод.
Параметры
value / cacheNames (обязательный параметр)
Имя кеша, в который сохраняется результат. Можно указать одно или несколько значений.
```
@Cacheable("usersCache")
```
key (опциональный)
Позволяет задать ключ для кеша. Если не указано, ключ формируется автоматически на основе аргументов метода.
Можно использовать SpEL (Spring Expression Language) для создания ключей.
```
@Cacheable(value = "usersCache", key = "#id")
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
```
condition (опциональный)
Условие, при котором результат метода будет закеширован. Используется SpEL. Если условие не выполнено, кеширование не происходит.
@Cacheable(value = "usersCache", condition = "#id > 10")
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
unless (опциональный)
Условие, при котором результат НЕ будет кешироваться, даже если метод выполнен. Отличается от condition, так как проверяется после выполнения метода.
@Cacheable(value = "usersCache", unless = "#result == null")
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
sync (опциональный)
Если true, запросы для одного и того же ключа будут синхронизированы, чтобы предотвратить одновременное выполнение метода для одного ключа.
@Cacheable(value = "usersCache", sync = true)
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
Пример использования
1. Простое кеширование
Кеширование результата метода:
@Cacheable("usersCache")
public User getUser(Long id) {
System.out.println("Fetching user from database...");
return userRepository.findById(id).orElse(null);
}
Первый вызов с ID 1 сохранит результат в кеше.
Повторные вызовы с тем же ID вернут кешированные данные.
2. Сложный ключ для кеша
@Cacheable(value = "usersCache", key = "#user.id + '-' + #user.name")
public User getUserWithCustomKey(User user) {
return userRepository.findById(user.getId()).orElse(null);
}
Здесь ключом будет строка, содержащая ID и имя пользователя.
3. Использование условий
@Cacheable(value = "usersCache", condition = "#id > 1000")
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
Данные кешируются только для ID больше 1000.
#Java #Training #Spring #Cacheable
@CacheEvict
Аннотация @CacheEvict используется для удаления записей из кеша. Это необходимо, когда данные в кеше устарели, например, после обновления или удаления записи.
Параметры
value / cacheNames (обязательный параметр)
Указывает имя кеша, из которого нужно удалить записи.
key (опциональный)
Указывает ключ, который нужно удалить. Если не указано, удаляется запись, соответствующая ключу, сформированному из аргументов метода.
allEntries (опциональный)
Если true, очищает весь кеш. Используется для полного удаления всех записей в кеше.
beforeInvocation (опциональный)
Если true, удаление из кеша происходит до выполнения метода. По умолчанию удаление происходит после успешного выполнения метода.
Примеры использования
1. Удаление записи из кеша по ключу
2. Очистка всего кеша
3. Очистка перед выполнением метода
Совместное использование @Cacheable и @CacheEvict
Эти аннотации можно использовать вместе для полного управления кешем.
Метод getProduct кеширует продукт.
Метод updateProduct удаляет устаревшие данные из кеша для обновлённого продукта.
Метод clearAllProductsCache очищает весь кеш продуктов.
Советы по использованию
Выбирайте правильный ключ: Убедитесь, что ключ уникален и логичен.
Учитывайте размер кеша: Не храните в кеше слишком большие данные.
Обновляйте кеш своевременно: Используйте @CacheEvict для предотвращения устаревания данных.
Избегайте чрезмерного кеширования: Не кешируйте часто изменяющиеся данные.
#Java #Training #Spring #Cacheable #CacheEvict
Аннотация @CacheEvict используется для удаления записей из кеша. Это необходимо, когда данные в кеше устарели, например, после обновления или удаления записи.
Параметры
value / cacheNames (обязательный параметр)
Указывает имя кеша, из которого нужно удалить записи.
@CacheEvict("usersCache")
key (опциональный)
Указывает ключ, который нужно удалить. Если не указано, удаляется запись, соответствующая ключу, сформированному из аргументов метода.
@CacheEvict(value = "usersCache", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
allEntries (опциональный)
Если true, очищает весь кеш. Используется для полного удаления всех записей в кеше.
@CacheEvict(value = "usersCache", allEntries = true)
public void clearCache() {
System.out.println("Cache cleared!");
}
beforeInvocation (опциональный)
Если true, удаление из кеша происходит до выполнения метода. По умолчанию удаление происходит после успешного выполнения метода.
@CacheEvict(value = "usersCache", key = "#id", beforeInvocation = true)
public void deleteUser(Long id) {
throw new RuntimeException("Error occurred!");
}
Примеры использования
1. Удаление записи из кеша по ключу
@CacheEvict(value = "usersCache", key = "#id")
public void updateUser(Long id, User user) {
userRepository.save(user);
}
Обновляем пользователя и удаляем устаревшие данные из кеша.
2. Очистка всего кеша
@CacheEvict(value = "usersCache", allEntries = true)
public void clearAllUsersCache() {
System.out.println("All users cache cleared!");
}
Этот метод полностью очищает кеш usersCache.
3. Очистка перед выполнением метода
@CacheEvict(value = "usersCache", key = "#id", beforeInvocation = true)
public void deleteUser(Long id) {
// Логика удаления пользователя
userRepository.deleteById(id);
}
Кеш удаляется перед удалением пользователя из базы.
Совместное использование @Cacheable и @CacheEvict
Эти аннотации можно использовать вместе для полного управления кешем.
@Service
public class ProductService {
@Cacheable("productCache")
public Product getProduct(Long id) {
System.out.println("Fetching product from database...");
return productRepository.findById(id).orElse(null);
}
@CacheEvict(value = "productCache", key = "#id")
public void updateProduct(Long id, Product product) {
System.out.println("Updating product in database...");
productRepository.save(product);
}
@CacheEvict(value = "productCache", allEntries = true)
public void clearAllProductsCache() {
System.out.println("Clearing all product cache...");
}
}
Метод getProduct кеширует продукт.
Метод updateProduct удаляет устаревшие данные из кеша для обновлённого продукта.
Метод clearAllProductsCache очищает весь кеш продуктов.
Советы по использованию
Выбирайте правильный ключ: Убедитесь, что ключ уникален и логичен.
Учитывайте размер кеша: Не храните в кеше слишком большие данные.
Обновляйте кеш своевременно: Используйте @CacheEvict для предотвращения устаревания данных.
Избегайте чрезмерного кеширования: Не кешируйте часто изменяющиеся данные.
#Java #Training #Spring #Cacheable #CacheEvict
Виды кеша в Spring и настройки конфигурации для Redis, Ehcache и Caffeine
Spring поддерживает разные провайдеры кеширования, что делает его универсальным инструментом. Настроим кеш для Redis, Ehcache и Caffeine.
1. Redis
Redis – это распределённый in-memory хранилище данных, которое поддерживает сложные структуры данных, TTL для кешей, и обеспечивает масштабируемость.
Нюансы работы с Redis
Хранение в памяти:
Все данные в Redis хранятся в оперативной памяти, что обеспечивает быструю скорость доступа.
Обязательно учитывайте объём данных и доступную оперативную память.
Поддержка TTL (время жизни):
Redis позволяет задавать время жизни для каждого ключа.
Это полезно для автоматического удаления устаревших данных.
Ключи кеша:
Redis кеширует данные по ключам, которые генерируются автоматически, если явно не указаны.
Рекомендуется явно задавать ключи с помощью параметра key в @Cacheable.
Проблемы с сериализацией:
Redis по умолчанию использует сериализацию JDK. Это может быть неэффективно.
Лучше использовать JSON-сериализацию, например, через Jackson.
Конкуренция за доступ к кешу:
Redis идеален для распределённых систем, но сетевые задержки могут влиять на производительность.
В локальных приложениях для небольших объёмов данных Redis использовать необязательно.
Шаги настройки Redis-кеша
Добавьте зависимости:
Настройте application.yml:
Конфигурация Redis-кеша:
#Java #Training #Spring #Redis
Spring поддерживает разные провайдеры кеширования, что делает его универсальным инструментом. Настроим кеш для Redis, Ehcache и Caffeine.
1. Redis
Redis – это распределённый in-memory хранилище данных, которое поддерживает сложные структуры данных, TTL для кешей, и обеспечивает масштабируемость.
Нюансы работы с Redis
Хранение в памяти:
Все данные в Redis хранятся в оперативной памяти, что обеспечивает быструю скорость доступа.
Обязательно учитывайте объём данных и доступную оперативную память.
Поддержка TTL (время жизни):
Redis позволяет задавать время жизни для каждого ключа.
Это полезно для автоматического удаления устаревших данных.
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))) // Устанавливаем TTL 10 минут
.build();
}
Ключи кеша:
Redis кеширует данные по ключам, которые генерируются автоматически, если явно не указаны.
Рекомендуется явно задавать ключи с помощью параметра key в @Cacheable.
@Cacheable(value = "productCache", key = "#id")
public Product getProductById(Long id) {
return productRepository.findById(id).orElse(null);
}
Проблемы с сериализацией:
Redis по умолчанию использует сериализацию JDK. Это может быть неэффективно.
Лучше использовать JSON-сериализацию, например, через Jackson.
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
return RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(
new GenericJackson2JsonRedisSerializer(objectMapper)
)
);
}
Конкуренция за доступ к кешу:
Redis идеален для распределённых систем, но сетевые задержки могут влиять на производительность.
В локальных приложениях для небольших объёмов данных Redis использовать необязательно.
Шаги настройки Redis-кеша
Добавьте зависимости:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce.core</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
Настройте application.yml:
spring:
redis:
host: localhost
port: 6379
cache:
type: redis
Конфигурация Redis-кеша:
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig())
.build();
}
}
Теперь кеширование данных с помощью Redis работает.
#Java #Training #Spring #Redis
2. Caffeine
Caffeine – это высокопроизводительная библиотека кеширования в памяти, которая отличается от Ehcache максимальной скоростью работы и расширенными возможностями.
Нюансы работы с Caffeine
Стратегии удаления:
Кеш автоматически удаляет устаревшие или редко используемые записи.
Поддерживаются три механизма:
Удаление на основе времени (TTL).
Удаление на основе неактивности (time-to-idle).
Удаление при достижении максимального размера.
Мониторинг:
Caffeine поддерживает метрики, что позволяет отслеживать использование кеша, количество попаданий и промахов.
Ленивая загрузка данных:
Caffeine позволяет автоматически загружать данные при промахе кеша.
Ограничения:
Как и Ehcache, Caffeine работает только локально.
Подходит для небольших и средних объёмов данных.
Шаги настройки Caffeine-кеша
Конфигурация Caffeine-кеша:
#Java #Training #Spring #Caffeine
Caffeine – это высокопроизводительная библиотека кеширования в памяти, которая отличается от Ehcache максимальной скоростью работы и расширенными возможностями.
Нюансы работы с Caffeine
Стратегии удаления:
Кеш автоматически удаляет устаревшие или редко используемые записи.
Поддерживаются три механизма:
Удаление на основе времени (TTL).
Удаление на основе неактивности (time-to-idle).
Удаление при достижении максимального размера.
Caffeine.newBuilder()
.maximumSize(500) // Максимум 500 записей
.expireAfterWrite(10, TimeUnit.MINUTES) // Удаление через 10 минут
.expireAfterAccess(5, TimeUnit.MINUTES) // Удаление через 5 минут неактивности
.build();
Мониторинг:
Caffeine поддерживает метрики, что позволяет отслеживать использование кеша, количество попаданий и промахов.
@Bean
public CaffeineCacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("usersCache");
cacheManager.setCaffeine(Caffeine.newBuilder()
.recordStats() // Включаем статистику
.maximumSize(1000));
return cacheManager;
}
Ленивая загрузка данных:
Caffeine позволяет автоматически загружать данные при промахе кеша.
LoadingCache<Long, User> userCache = Caffeine.newBuilder()
.maximumSize(100)
.build(id -> loadUserById(id)); // Метод для загрузки данных
Ограничения:
Как и Ehcache, Caffeine работает только локально.
Подходит для небольших и средних объёмов данных.
Шаги настройки Caffeine-кеша
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
Конфигурация Caffeine-кеша:
@Configuration
@EnableCaching
public class CaffeineCacheConfig {
@Bean
public CaffeineCacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("usersCache");
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(100)
.maximumSize(500)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats());
return cacheManager;
}
}
Теперь кеширование данных с Caffeine готово.
#Java #Training #Spring #Caffeine
3. Ehcache
Ehcache – это высокопроизводительный провайдер кеша, который работает локально в памяти приложения. Он также поддерживает персистентность данных.
Нюансы работы с Ehcache
Хранение данных:
Данные кешируются в памяти, но могут быть настроены для сохранения на диск (для долговременного хранения).
Конфигурация TTL и TTI:
TTL (time-to-live) определяет максимальное время хранения записи.
TTI (time-to-idle) сбрасывается при каждом доступе к записи.
Гибкость настройки:
Ehcache можно настроить с разной стратегией хранения, например, только в памяти или с поддержкой записи на диск.
Ограничения:
Ehcache работает только локально, что делает его менее подходящим для распределённых систем.
В высоконагруженных приложениях использование кеша в памяти может быть ограничено объёмом оперативной памяти.
Шаги настройки Ehcache
Создайте конфигурацию Ehcache (ehcache.xml):
Конфигурация Spring для Ehcache:
Рекомендации по выбору
Используйте Redis, если:
Вам нужно кеширование в распределённой системе.
Данные должны быть доступны всем экземплярам приложения.
Есть потребность в масштабируемости и гибкости.
Используйте Ehcache, если:
Вы хотите локальное кеширование с минимальными задержками.
Вам важна поддержка дисковой персистентности.
Используйте Caffeine, если:
Вы ищете максимальную производительность и минимальное потребление ресурсов.
Приложение работает локально и не требует масштабируемости.
#Java #Training #Spring #Ehcache
Ehcache – это высокопроизводительный провайдер кеша, который работает локально в памяти приложения. Он также поддерживает персистентность данных.
Нюансы работы с Ehcache
Хранение данных:
Данные кешируются в памяти, но могут быть настроены для сохранения на диск (для долговременного хранения).
<cache alias="persistentCache">
<heap unit="entries">1000</heap>
<disk persistent="true" directory="./cache-data" />
</cache>
Конфигурация TTL и TTI:
TTL (time-to-live) определяет максимальное время хранения записи.
TTI (time-to-idle) сбрасывается при каждом доступе к записи.
<cache alias="myCache">
<heap unit="entries">500</heap>
<expiry>
<ttl unit="seconds">300</ttl> <!-- 5 минут -->
<tti unit="seconds">60</tti> <!-- 1 минута неактивности -->
</expiry>
</cache>
Гибкость настройки:
Ehcache можно настроить с разной стратегией хранения, например, только в памяти или с поддержкой записи на диск.
Ограничения:
Ehcache работает только локально, что делает его менее подходящим для распределённых систем.
В высоконагруженных приложениях использование кеша в памяти может быть ограничено объёмом оперативной памяти.
Шаги настройки Ehcache
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
Создайте конфигурацию Ehcache (ehcache.xml):
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.ehcache.org/v3">
<cache alias="myCache">
<heap unit="entries">100</heap>
<expiry>
<ttl unit="seconds">300</ttl>
</expiry>
</cache>
</config>
Конфигурация Spring для Ehcache:
@Configuration
@EnableCaching
public class EhcacheConfig {
@Bean
public CacheManager cacheManager() {
return new EhCacheCacheManager(CacheManager.newInstance("ehcache.xml"));
}
}
Теперь можно использовать кеширование с Ehcache.
Рекомендации по выбору
Используйте Redis, если:
Вам нужно кеширование в распределённой системе.
Данные должны быть доступны всем экземплярам приложения.
Есть потребность в масштабируемости и гибкости.
Используйте Ehcache, если:
Вы хотите локальное кеширование с минимальными задержками.
Вам важна поддержка дисковой персистентности.
Используйте Caffeine, если:
Вы ищете максимальную производительность и минимальное потребление ресурсов.
Приложение работает локально и не требует масштабируемости.
#Java #Training #Spring #Ehcache
Что выведет код?
#Tasks
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Task291124_1 {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2024, 2, 28);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String formattedDate = date.plusDays(1).format(formatter);
String nextMonth = date.plusMonths(1).format(formatter);
System.out.println(formattedDate);
System.out.println(nextMonth);
}
}
#Tasks
Варианты ответа:
Anonymous Quiz
60%
2024-02-29 2024-03-28
10%
2024-03-01 2024-03-28
20%
2024-02-29 2024-03-01
10%
2024-03-01 2024-03-29
Примеры использования кеша на примере Caffeine и Redis
1. Пример с использованием Caffeine
Допустим, у нас есть метод, который возвращает данные пользователя.
Проверка:
Первый вызов getUserById(1L) загрузит данные из базы.
Повторный вызов вернёт данные из кеша.
Метод updateUser(1L, user) очистит устаревшие данные из кеша.
Вывод: Кеш на базе Caffeine идеально подходит для небольших объёмов данных с высокой скоростью работы.
2. Пример с использованием Redis
Допустим, мы создаём приложение, где кеш хранится в Redis.
Проверка:
При вызове getProductById(1L) данные сохраняются в Redis.
Повторный вызов с тем же ID возвращает данные из Redis без обращения к базе.
Метод updateProduct(1L, product) удаляет кешированные данные.
Преимущества Redis:
Данные доступны для всех экземпляров приложения в распределённой системе.
Redis поддерживает TTL (время жизни кеша), что удобно для управления устареванием данных.
#Java #Training #Spring #Caffeine #Redis
1. Пример с использованием Caffeine
Допустим, у нас есть метод, который возвращает данные пользователя.
@Service
public class UserService {
@Cacheable("usersCache")
public User getUserById(Long id) {
System.out.println("Fetching user from database...");
// Имитация запроса к базе данных
return new User(id, "User" + id);
}
@CacheEvict(value = "usersCache", key = "#id")
public void updateUser(Long id, User user) {
System.out.println("Updating user in database...");
// Обновление в базе
}
}
Проверка:
Первый вызов getUserById(1L) загрузит данные из базы.
Повторный вызов вернёт данные из кеша.
Метод updateUser(1L, user) очистит устаревшие данные из кеша.
Вывод: Кеш на базе Caffeine идеально подходит для небольших объёмов данных с высокой скоростью работы.
2. Пример с использованием Redis
Допустим, мы создаём приложение, где кеш хранится в Redis.
@Service
public class ProductService {
@Cacheable("productCache")
public Product getProductById(Long id) {
System.out.println("Fetching product from database...");
// Имитация запроса к базе данных
return new Product(id, "Product" + id);
}
@CacheEvict(value = "productCache", key = "#id")
public void updateProduct(Long id, Product product) {
System.out.println("Updating product in database...");
// Обновление в базе
}
}
Проверка:
При вызове getProductById(1L) данные сохраняются в Redis.
Повторный вызов с тем же ID возвращает данные из Redis без обращения к базе.
Метод updateProduct(1L, product) удаляет кешированные данные.
Преимущества Redis:
Данные доступны для всех экземпляров приложения в распределённой системе.
Redis поддерживает TTL (время жизни кеша), что удобно для управления устареванием данных.
#Java #Training #Spring #Caffeine #Redis
Что выведет код?
Задача по aннотации @Transactional, аннотациям @Cacheable и @CacheEvict, симуляция кеша в Spring. Сложность легкая.
Подробный разбор через 30 минут!🫡
#TasksSpring
Задача по aннотации @Transactional, аннотациям @Cacheable и @CacheEvict, симуляция кеша в Spring. Сложность легкая.
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
@EnableCaching
public class Task291124_2 {
public static void main(String[] args) {
SpringApplication.run(Task291124_2.class, args);
}
@Bean
public CommandLineRunner demo(UserService2911 userService) {
return args -> {
System.out.println(userService.getUserById(1L));
System.out.println(userService.getUserById(1L));
userService.clearCache();
System.out.println(userService.getUserById(1L));
};
}
}
@Service
class UserService2911 {
private final Map<Long, String> database = new HashMap<>();
public UserService2911() {
database.put(1L, "Alice");
}
@Cacheable("users")
public String getUserById(Long id) {
System.out.println("Fetching user from database...");
return database.get(id);
}
@CacheEvict(value = "users", allEntries = true)
public void clearCache() {
System.out.println("Cache cleared");
}
@Transactional
public void updateUser(Long id, String newName) {
database.put(id, newName);
if (newName == null) {
throw new IllegalArgumentException("Name cannot be null");
}
}
}
#TasksSpring
Подробный разбор решения задачи Task291124_2
1. Контекст задачи
Задача исследует использование аннотаций Spring для работы с кешированием (@Cacheable, @CacheEvict) и транзакциями (@Transactional). Также рассматривается, как Spring управляет кешем, обрабатывает транзакции и вызывает базовые CRUD операции.
2. Ключевые элементы кода
Аннотация @SpringBootApplication:
Указывает, что Task291124_2 — это основной класс Spring Boot приложения. Он автоматически настраивает компоненты приложения, включая механизмы кеширования и управления транзакциями.
Аннотация @EnableCaching:
Разрешает проведение кеширования. Без включения @EnableCaching Spring не активирует кеширование, и @Cacheable не работает.
Аннотация @Service:
UserService2911 помечен как сервисный компонент, что делает его доступным в контексте Spring для внедрения зависимостей.
Кеширование с помощью аннотаций @Cacheable и @CacheEvict:
@Cacheable("users"): Метод getUserById(Long id) кеширует результат выполнения с ключом, основанным на значении параметра id. Если вызов осуществляется с тем же id, результат извлекается из кеша, и метод повторно не выполняется.
@CacheEvict(value = "users", allEntries = true): Метод clearCache() очищает кеш для всех записей в кеше users.
Транзакционное управление с помощью @Transactional:
Метод updateUser(Long id, String newName) помечен как транзакционный. Если во время выполнения метода происходит исключение, транзакция откатывается, и изменения в базе данных не применяются.
Симуляция базы данных:
Данные хранятся в объекте Map<Long, String> database, который используется как простая "база данных". В данном случае только один пользователь (Alice) с id = 1L изначально добавлен в "базу".
Использование CommandLineRunner:
Метод demo() выполняет тестовый код сразу после запуска приложения. Он вызывает методы getUserById() и clearCache(), демонстрируя поведение кеширования.
3. Сценарий работы программы
Запуск приложения:
Программа запускается через SpringApplication.run(Main2911.class, args);, и Spring Boot автоматически настраивает кеширование, транзакции и остальные компоненты приложения.
Первый вызов getUserById(1L):
Метод getUserById(1L) вызывается первый раз. Поскольку кеш для ключа 1L еще не существует, данные извлекаются из "базы данных" (Map), выводится:
Результат ("Alice") добавляется в кеш и возвращается.
Второй вызов getUserById(1L):
Метод вызывается снова с тем же параметром 1L. Поскольку результат уже находится в кеше, он извлекается из кеша без повторного обращения к "базе данных". Никакого сообщения о запросе к базе данных не выводится, а результат ("Alice") возвращается напрямую.
Вызов clearCache():
Метод clearCache() вызывается, что очищает кеш для всех записей в кеше users. В консоль выводится сообщение:
Третий вызов getUserById(1L):
После очистки кеша метод снова вызывается с параметром 1L. Поскольку кеш был очищен, данные снова извлекаются из "базы данных".
Вывод:
Результат ("Alice") возвращается и снова кешируется.
4. Ключевые моменты и выводы
Механизм кеширования:
Аннотация @Cacheable кеширует результат выполнения метода, что предотвращает повторное выполнение, если запрос уже был обработан ранее.
Аннотация @CacheEvict используется для очистки кеша. В данном случае allEntries = true очищает все записи в кеше users.
Транзакционное управление:
Метод updateUser() не используется в задаче, но он демонстрирует работу транзакций. Если в процессе обновления пользовательского имени возникает исключение (например, при передаче null), транзакция откатывается, и изменения в базе данных не применяются.
Проверка работы кеша:
Первый вызов метода getUserById() выполняет запрос к "базе данных", а второй использует кеш.
После вызова clearCache() кеш очищается, и следующий вызов метода снова выполняет запрос к базе.
#Solution_TasksSpring
1. Контекст задачи
Задача исследует использование аннотаций Spring для работы с кешированием (@Cacheable, @CacheEvict) и транзакциями (@Transactional). Также рассматривается, как Spring управляет кешем, обрабатывает транзакции и вызывает базовые CRUD операции.
2. Ключевые элементы кода
Аннотация @SpringBootApplication:
Указывает, что Task291124_2 — это основной класс Spring Boot приложения. Он автоматически настраивает компоненты приложения, включая механизмы кеширования и управления транзакциями.
Аннотация @EnableCaching:
Разрешает проведение кеширования. Без включения @EnableCaching Spring не активирует кеширование, и @Cacheable не работает.
Аннотация @Service:
UserService2911 помечен как сервисный компонент, что делает его доступным в контексте Spring для внедрения зависимостей.
Кеширование с помощью аннотаций @Cacheable и @CacheEvict:
@Cacheable("users"): Метод getUserById(Long id) кеширует результат выполнения с ключом, основанным на значении параметра id. Если вызов осуществляется с тем же id, результат извлекается из кеша, и метод повторно не выполняется.
@CacheEvict(value = "users", allEntries = true): Метод clearCache() очищает кеш для всех записей в кеше users.
Транзакционное управление с помощью @Transactional:
Метод updateUser(Long id, String newName) помечен как транзакционный. Если во время выполнения метода происходит исключение, транзакция откатывается, и изменения в базе данных не применяются.
Симуляция базы данных:
Данные хранятся в объекте Map<Long, String> database, который используется как простая "база данных". В данном случае только один пользователь (Alice) с id = 1L изначально добавлен в "базу".
Использование CommandLineRunner:
Метод demo() выполняет тестовый код сразу после запуска приложения. Он вызывает методы getUserById() и clearCache(), демонстрируя поведение кеширования.
3. Сценарий работы программы
Запуск приложения:
Программа запускается через SpringApplication.run(Main2911.class, args);, и Spring Boot автоматически настраивает кеширование, транзакции и остальные компоненты приложения.
Первый вызов getUserById(1L):
Метод getUserById(1L) вызывается первый раз. Поскольку кеш для ключа 1L еще не существует, данные извлекаются из "базы данных" (Map), выводится:
Fetching user from database...
Результат ("Alice") добавляется в кеш и возвращается.
Второй вызов getUserById(1L):
Метод вызывается снова с тем же параметром 1L. Поскольку результат уже находится в кеше, он извлекается из кеша без повторного обращения к "базе данных". Никакого сообщения о запросе к базе данных не выводится, а результат ("Alice") возвращается напрямую.
Вызов clearCache():
Метод clearCache() вызывается, что очищает кеш для всех записей в кеше users. В консоль выводится сообщение:
Cache cleared
Третий вызов getUserById(1L):
После очистки кеша метод снова вызывается с параметром 1L. Поскольку кеш был очищен, данные снова извлекаются из "базы данных".
Вывод:
Fetching user from database...
Результат ("Alice") возвращается и снова кешируется.
4. Ключевые моменты и выводы
Механизм кеширования:
Аннотация @Cacheable кеширует результат выполнения метода, что предотвращает повторное выполнение, если запрос уже был обработан ранее.
Аннотация @CacheEvict используется для очистки кеша. В данном случае allEntries = true очищает все записи в кеше users.
Транзакционное управление:
Метод updateUser() не используется в задаче, но он демонстрирует работу транзакций. Если в процессе обновления пользовательского имени возникает исключение (например, при передаче null), транзакция откатывается, и изменения в базе данных не применяются.
Проверка работы кеша:
Первый вызов метода getUserById() выполняет запрос к "базе данных", а второй использует кеш.
После вызова clearCache() кеш очищается, и следующий вызов метода снова выполняет запрос к базе.
#Solution_TasksSpring
Всем доброго утра!🖐
Не знаю что писать в субботу с утра)))
Поэтому просто пожелаю Вам хороших выходных😉
А если кому скучно - жду вас в нашем чате - https://t.me/Java_Beginner_chat
Не знаю что писать в субботу с утра)))
Поэтому просто пожелаю Вам хороших выходных😉
А если кому скучно - жду вас в нашем чате - https://t.me/Java_Beginner_chat
Всем привет!🖐
Сегодня в 16:00 по МСК мы вновь встречаемся в том же месте!(Яндекс.Телемост, кто не понял)
@VladislavSlavName потренируется в написании web-приложения, а Вы можете составить ему компанию✊
Ждем всех!💪
Сегодня в 16:00 по МСК мы вновь встречаемся в том же месте!
@VladislavSlavName потренируется в написании web-приложения, а Вы можете составить ему компанию✊
Ждем всех!💪
Встреча_в_Телемосте_01_12_24_20_02_00_—_запись.webm
182.9 MB
Простое Web приложение, обучение аннотации @Query
Спасибо всем кто пришел, за участие! ✊
Отдельная благодарность @VladislavSlavName что незассал (побоялся) и показал нам свои знания 💪
На сегодняшней встрече мы написали простое Web приложение, разобрали работу каждой использованной аннотации, класса и метода, изучили аннотацию @Query.
Прикладываю запись, если кто-то пожелает пересмотреть)
Спасибо всем кто пришел, за участие! ✊
Отдельная благодарность @VladislavSlavName что не
На сегодняшней встрече мы написали простое Web приложение, разобрали работу каждой использованной аннотации, класса и метода, изучили аннотацию @Query.
Прикладываю запись, если кто-то пожелает пересмотреть)
Основы аспектно-ориентированного программирования (AOP) в Spring
Аспектно-ориентированное программирование (AOP) – это подход, позволяющий разделять сквозную функциональность приложения (например, логирование, безопасность, транзакции) от основной логики. AOP в Spring является мощным инструментом для управления поведением приложения, упрощая код и повышая его модульность.
AOP — это методология программирования, которая вводит концепцию аспектов. Аспект – это модуль, содержащий сквозную функциональность, которую можно применить к разным частям программы без изменения их исходного кода.
Основные концепции AOP
Аспект (Aspect)
Модуль, содержащий сквозную функциональность (например, логирование или авторизацию).
Точка соединения (Join Point)
Определённое место в программе, где можно "вставить" аспект. Например, вызов метода, создание объекта.
Срез (Pointcut)
Условие, определяющее, на какие точки соединения должен применяться аспект.
Совет (Advice)
Логика, которая выполняется на основе среза. Типы советов:
@Before: выполняется до вызова метода.
@After: выполняется после завершения метода.
@AfterReturning: выполняется, если метод завершился успешно.
@AfterThrowing: выполняется при возникновении исключения.
@Around: оборачивает выполнение метода, позволяет управлять его выполнением.
Как включить AOP в Spring?
Добавьте зависимость в проект: Для использования AOP в Spring Boot:
Включите поддержку AOP: Добавьте аннотацию @EnableAspectJAutoProxy в ваш @Configuration класс.
Создайте аспект:
Создайте бизнес-логику:
Результат:
Вызов метода getUserById(1L) сначала выполняет логику @Before, а затем основную логику метода.
Пример с логированием (совет @Around):
#Java #Training #Spring #AOP
Аспектно-ориентированное программирование (AOP) – это подход, позволяющий разделять сквозную функциональность приложения (например, логирование, безопасность, транзакции) от основной логики. AOP в Spring является мощным инструментом для управления поведением приложения, упрощая код и повышая его модульность.
AOP — это методология программирования, которая вводит концепцию аспектов. Аспект – это модуль, содержащий сквозную функциональность, которую можно применить к разным частям программы без изменения их исходного кода.
Основные концепции AOP
Аспект (Aspect)
Модуль, содержащий сквозную функциональность (например, логирование или авторизацию).
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("Logging before method execution");
}
}
Точка соединения (Join Point)
Определённое место в программе, где можно "вставить" аспект. Например, вызов метода, создание объекта.
Срез (Pointcut)
Условие, определяющее, на какие точки соединения должен применяться аспект.
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayerMethods() {}
Совет (Advice)
Логика, которая выполняется на основе среза. Типы советов:
@Before: выполняется до вызова метода.
@After: выполняется после завершения метода.
@AfterReturning: выполняется, если метод завершился успешно.
@AfterThrowing: выполняется при возникновении исключения.
@Around: оборачивает выполнение метода, позволяет управлять его выполнением.
@Before("serviceLayerMethods()")
public void logBeforeServiceMethod() {
System.out.println("Executing service method...");
}
Как включить AOP в Spring?
Добавьте зависимость в проект: Для использования AOP в Spring Boot:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Включите поддержку AOP: Добавьте аннотацию @EnableAspectJAutoProxy в ваш @Configuration класс.
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {}
Создайте аспект:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("Method execution intercepted by AOP.");
}
}
Создайте бизнес-логику:
@Service
public class UserService {
public void getUserById(Long id) {
System.out.println("Getting user by ID: " + id);
}
}
Результат:
Вызов метода getUserById(1L) сначала выполняет логику @Before, а затем основную логику метода.
Пример с логированием (совет @Around):
@Aspect
@Component
public class PerformanceLoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // Выполнение метода
long executionTime = System.currentTimeMillis() - start;
System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
return result;
}
}
Теперь при вызове методов сервисного слоя будет логироваться время выполнения.
#Java #Training #Spring #AOP
Что выведет код?
#Tasks
import java.util.ArrayList;
import java.util.List;
public class Task021224_1 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
list.add(i * i);
}
list.add(2, 10);
list.set(0, list.get(3));
list.remove(Integer.valueOf(16));
for (int i = 0; i < list.size(); i++) {
list.set(i, list.get(i) % 7);
}
System.out.println(list);
}
}
#Tasks
Варианты ответа:
Anonymous Quiz
14%
[4, 2, 3, 1, 0]
43%
[3, 2, 3, 4, 5]
36%
[2, 4, 3, 2, 4]
7%
[2, 2, 3, 1, 4]