🎥 Открытый урок «Eclipse Memory Analyzer (MAT): помощь в работе с heap».
🗓 04 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Advanced».
Что будет на вебинаре:
✔️ Ключевые концепции работы с MAT и навигация по heap dump.
✔️ Экспресс-анализ дампа памяти: где искать утечки и рост объектов.
✔️ Разбор реального дампа в онлайне на предмет memory leak.
В результате вебинара:
Вы сможете самостоятельно проводить анализ дампов памяти. Будете знать возможности MAT и какие задачи решаются с его помощью.
Кому будет интересно:
Подойдёт Java-разработчикам, инженерам сопровождения и SRE, кто сталкивается с OutOfMemoryError и падениями по памяти.
🔗 Ссылка на регистрацию: https://vk.cc/cU0oou
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🗓 04 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Advanced».
Без MAT сложно найти причины OutOfMemoryError и утечек. Разберём базу и полезные приёмы анализа heap dump.
Что будет на вебинаре:
В результате вебинара:
Вы сможете самостоятельно проводить анализ дампов памяти. Будете знать возможности MAT и какие задачи решаются с его помощью.
Кому будет интересно:
Подойдёт Java-разработчикам, инженерам сопровождения и SRE, кто сталкивается с OutOfMemoryError и падениями по памяти.
🔗 Ссылка на регистрацию: https://vk.cc/cU0oou
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Redis + Spring Cache: Турбо-наддув для бэкенда
Самая медленная часть любого приложения это ввод-вывод (I/O). Поход в базу данных (Postgres/MySQL) это "долго" (миллисекунды). Поход в оперативную память это "мгновенно" (наносекунды).
Redis - это база данных, которая хранит всё в оперативной памяти (In-Memory). Она идеально подходит на роль кэша.
🧠 Как работает Spring Cache?
Spring предоставляет крутую абстракцию. Вам не нужно писать код для подключения к Redis в каждом методе. Вы просто вешаете аннотации, а Spring сам перехватывает вызов метода.
Алгоритм
1. Вызывается метод
2. Spring лезет в кэш (Redis) по ключу
3. Если данные есть (Cache Hit): Spring НЕ выполняет код метода, а сразу возвращает данные из кэша.
4. Если данных нет (Cache Miss): Spring выполняет метод (идет в БД), берет результат, кладет его в кэш и отдает вам.
🛠 Настройка (2 шага)
1. Зависимости
В
2. Включаем рубильник
Над главным классом вешаем
💻 Магия аннотаций
У нас есть 3 главные аннотации, которые вы обязаны знать:
1.
Вешаем над методами поиска (
Результат: Первый вызов займет 3 секунды. Второй, третий и тысячный вызов с тем же ID займут 0.001 секунды.
2.
Самая большая проблема кэширования - инвалидация. Если мы обновили данные юзера в БД, а в кэше осталась старая версия — это баг.
При обновлении или удалении мы должны очистить кэш.
Теперь при следующем вызове
3.
Используется реже. Метод выполняется всегда, а его результат кладется в кэш, обновляя старое значение.
🆚 Redis vs HashMap
"Зачем мне Redis, если я могу создать
1. Память: Если данных много,
2. Микросервисы: Если у вас запущено 3 экземпляра сервиса, у каждого будет свой
3. Живучесть: При перезагрузке приложения
⚠️ Важный нюанс: Serializable
Чтобы положить Java-объект в Redis, его нужно превратить в байты (сериализовать).
Ваши DTO и Entity должны реализовывать интерфейс
🔥 Итог: кэширование - это самый простой способ масштабирования.
🔴 Часто читаете, редко меняете? ->
🔴 Удалили/Обновили? ->
#Java #Spring #Redis #Caching #Performance
📲 Мы в MAX
👉@BookJava
Самая медленная часть любого приложения это ввод-вывод (I/O). Поход в базу данных (Postgres/MySQL) это "долго" (миллисекунды). Поход в оперативную память это "мгновенно" (наносекунды).
Redis - это база данных, которая хранит всё в оперативной памяти (In-Memory). Она идеально подходит на роль кэша.
🧠 Как работает Spring Cache?
Spring предоставляет крутую абстракцию. Вам не нужно писать код для подключения к Redis в каждом методе. Вы просто вешаете аннотации, а Spring сам перехватывает вызов метода.
Алгоритм
@Cacheable:1. Вызывается метод
getUser(1).2. Spring лезет в кэш (Redis) по ключу
user::1.3. Если данные есть (Cache Hit): Spring НЕ выполняет код метода, а сразу возвращает данные из кэша.
4. Если данных нет (Cache Miss): Spring выполняет метод (идет в БД), берет результат, кладет его в кэш и отдает вам.
🛠 Настройка (2 шага)
1. Зависимости
В
pom.xml добавляем стартер для кэша и драйвер Redis:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. Включаем рубильник
Над главным классом вешаем
@EnableCaching.💻 Магия аннотаций
У нас есть 3 главные аннотации, которые вы обязаны знать:
1.
@Cacheable — "Запомни меня"Вешаем над методами поиска (
get, find).
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
// Имитация долгого запроса в БД (3 секунды)
simulateSlowService();
return userRepository.findById(id).orElseThrow();
}
}
Результат: Первый вызов займет 3 секунды. Второй, третий и тысячный вызов с тем же ID займут 0.001 секунды.
2.
@CacheEvict - "Забудь меня"Самая большая проблема кэширования - инвалидация. Если мы обновили данные юзера в БД, а в кэше осталась старая версия — это баг.
При обновлении или удалении мы должны очистить кэш.
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
Теперь при следующем вызове
getUserById(id) Spring увидит, что кэш пуст, и снова сходит в БД за свежими данными.3.
@CachePut - "Обнови меня"Используется реже. Метод выполняется всегда, а его результат кладется в кэш, обновляя старое значение.
🆚 Redis vs HashMap
"Зачем мне Redis, если я могу создать
ConcurrentHashMap прямо в Java?"1. Память: Если данных много,
HashMap съест всю память JVM, и приложение упадет (OutOfMemory). Redis живет отдельно.2. Микросервисы: Если у вас запущено 3 экземпляра сервиса, у каждого будет свой
HashMap. Кэш будет рассинхронизирован. Redis это общий кэш для всех инстансов.3. Живучесть: При перезагрузке приложения
HashMap очищается. Redis (обычно) работает на отдельном сервере и хранит данные даже при рестарте вашего кода.⚠️ Важный нюанс: Serializable
Чтобы положить Java-объект в Redis, его нужно превратить в байты (сериализовать).
Ваши DTO и Entity должны реализовывать интерфейс
Serializable, либо (что правильнее) нужно настроить Jackson Serializer, чтобы хранить данные в Redis в читаемом JSON-формате.🔥 Итог: кэширование - это самый простой способ масштабирования.
@Cacheable.@CacheEvict.#Java #Spring #Redis #Caching #Performance
📲 Мы в MAX
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
👮♂️ Spring Security: Фейсконтроль для вашего API
Spring Security - это не просто библиотека, это мощный фреймворк, который встает стеной между интернетом и вашим контроллером.
Его работа строится на концепции Filter Chain (Цепочка фильтров). Каждый запрос проходит через серию проверок: "Есть ли токен?", "Валиден ли он?", "Есть ли права?".
🔑 Authentication vs Authorization
Два слова, которые путают все джуниоры.
1. Authentication (Аутентификация): "Кто ты?"
🔴 Ввод логина/пароля.
🔴 Проверка отпечатка пальца.
🔴 Ответ: 401 Unauthorized (если не знаем, кто это).
2. Authorization (Авторизация): "А что тебе можно?"
🔴 Ты Вася (мы тебя узнали), но ты хочешь удалить базу данных. Тебе нельзя.
🔴 Ответ: 403 Forbidden (знаем кто ты, но не пустим).
🎫 JWT (JSON Web Token) - Паспорт туриста
В микросервисах мы не храним состояние пользователя на сервере (Stateless). Вместо этого, при логине мы выдаем пользователю Токен.
JWT - это строка из трех частей, разделенных точками:
🔴 Payload: Полезные данные (User ID, Role, Email).
🔴 Signature: Цифровая подпись сервера. Гарантирует, что хитрый хакер не поменял в токене роль
Как это работает:
1. Клиент шлет Логин/Пароль -> Сервер проверяет и отдает JWT.
2. Клиент сохраняет JWT (обычно в LocalStorage браузера).
3. При каждом запросе клиент прикрепляет JWT в заголовок:
4. Сервер видит токен, проверяет подпись и пускает (не ходя в базу данных!).
🛡 Настройка (Spring Boot 3.x)
Раньше мы наследовались от
Сейчас мы просто объявляем бин
🔓 Что такое OAuth2?
JWT - это когда вы сами выдаете токены.
OAuth2 - это когда токены выдает кто-то большой и доверенный (Google, Facebook, GitHub).
Кнопка "Войти через Google" - это OAuth2.
1. Вы перенаправляете юзера на Google.
2. Google спрашивает: "Разрешить приложению MyShop узнать ваш email?".
3. Google возвращает вам токен.
4. Вы верите этому токену, потому что доверяете Google.
В Spring Boot это настраивается буквально в 5 строк в
🔥 Итог: безопасность для бэкенда это:
1. Spring Security как движок.
2. JWT как пропуск.
3. Stateless режим (без сессий).
4. HTTPS (обязательно, иначе токен украдут).
#SpringSecurity #JWT #OAuth2 #Java #CyberSecurity
📲 Мы в MAX
👉@BookJava
Spring Security - это не просто библиотека, это мощный фреймворк, который встает стеной между интернетом и вашим контроллером.
Его работа строится на концепции Filter Chain (Цепочка фильтров). Каждый запрос проходит через серию проверок: "Есть ли токен?", "Валиден ли он?", "Есть ли права?".
🔑 Authentication vs Authorization
Два слова, которые путают все джуниоры.
1. Authentication (Аутентификация): "Кто ты?"
2. Authorization (Авторизация): "А что тебе можно?"
🎫 JWT (JSON Web Token) - Паспорт туриста
В микросервисах мы не храним состояние пользователя на сервере (Stateless). Вместо этого, при логине мы выдаем пользователю Токен.
JWT - это строка из трех частей, разделенных точками:
Header.Payload.Signature.USER на ADMIN.Как это работает:
1. Клиент шлет Логин/Пароль -> Сервер проверяет и отдает JWT.
2. Клиент сохраняет JWT (обычно в LocalStorage браузера).
3. При каждом запросе клиент прикрепляет JWT в заголовок:
Authorization: Bearer <token>4. Сервер видит токен, проверяет подпись и пускает (не ходя в базу данных!).
🛡 Настройка (Spring Boot 3.x)
Раньше мы наследовались от
WebSecurityConfigurerAdapter. Забудьте, этот класс Deprecated.Сейчас мы просто объявляем бин
SecurityFilterChain.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable) // Для REST API отключаем
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // Никаких сессий!
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll() // Логин доступен всем
.requestMatchers("/admin/**").hasRole("ADMIN") // Админка только админам
.anyRequest().authenticated() // Всё остальное - только с токеном
)
// Добавляем наш кастомный фильтр для проверки JWT
.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
🔓 Что такое OAuth2?
JWT - это когда вы сами выдаете токены.
OAuth2 - это когда токены выдает кто-то большой и доверенный (Google, Facebook, GitHub).
Кнопка "Войти через Google" - это OAuth2.
1. Вы перенаправляете юзера на Google.
2. Google спрашивает: "Разрешить приложению MyShop узнать ваш email?".
3. Google возвращает вам токен.
4. Вы верите этому токену, потому что доверяете Google.
В Spring Boot это настраивается буквально в 5 строк в
application.yaml, но под капотом там огромная машина стандартов.🔥 Итог: безопасность для бэкенда это:
1. Spring Security как движок.
2. JWT как пропуск.
3. Stateless режим (без сессий).
4. HTTPS (обязательно, иначе токен украдут).
#SpringSecurity #JWT #OAuth2 #Java #CyberSecurity
📲 Мы в MAX
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2
А вы справитесь с тестом по HighLoad?
Как пройти путь от разработчика до архитектора высоконагруженных систем для работы с крупными проектами?
Пройдите тест, проверьте свои знания для обучения на курсе «Highload Architect» от OTUS. А так же и получите скидку🎁 до 15.02.2026 - подробности у менеджера.
➡️ Пройти Тест https://vk.cc/cU6fLb
На курсе вы освоите проектирование масштабируемых и отказоустойчивых систем, оптимизацию производительности, работу с современными инструментами для создания высоконагруженных решений и лучшие практики разработки серверных приложений.
❗️ Практическое обучение проводится в прямом эфире — вебинары не являются предзаписанными.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Как пройти путь от разработчика до архитектора высоконагруженных систем для работы с крупными проектами?
Пройдите тест, проверьте свои знания для обучения на курсе «Highload Architect» от OTUS. А так же и получите скидку
На курсе вы освоите проектирование масштабируемых и отказоустойчивых систем, оптимизацию производительности, работу с современными инструментами для создания высоконагруженных решений и лучшие практики разработки серверных приложений.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🏗 SOLID - Пять заповедей программиста
Почему один проект живет 10 лет и его легко дорабатывать, а другой через полгода превращается в "Legacy", к которому страшно подходить?
Разница в соблюдении принципов SOLID.
Это аббревиатура из 5 правил, сформулированных Робертом Мартином (Дядя Боб). Если вы нарушаете их - ваш код "гниет".
Давайте разберем каждую букву.
1️⃣ S - Single Responsibility Principle (Единственная ответственность)
⛔ Как делают новички (God Object):
Класс
1. Считает сумму заказа.
2. Сохраняет заказ в БД.
3. Отправляет email клиенту.
4. Генерирует PDF-чек.
Если бизнес попросит изменить формат чека — мы лезем в этот класс. Если поменяется логика БД - опять в него. Риск сломать отправку писем при правке базы данных огромен!
✅ Как надо:
Разбиваем на маленькие классы:
•
•
•
•
2️⃣ O - Open-Closed Principle (Открытость/Закрытость)
Это значит: Не меняйте старый рабочий код, чтобы добавить новую фичу.
⛔ Плохо:
У нас есть метод расчета доставки.
✅ Хорошо:
Используем полиморфизм.
3️⃣ L - Liskov Substitution Principle (Принцип подстановки Барбары Лисков)
Если у вас есть класс
Суть: Если код работает с базовым классом, он должен работать и с любым его наследником, не зная об этом и не ломаясь.
4️⃣ I - Interface Segregation Principle (Разделение интерфейсов)
⛔ Плохо:
Интерфейс
Мы создаем класс
Нам придется реализовать метод
✅ Хорошо:
Разбейте на
Человек имплементирует оба. Робот - только
5️⃣ D - Dependency Inversion Principle (Инверсия зависимостей)
Это то, что мы учили в Spring (DI).
Ваш
Тогда вы сможете легко подменить Postgres на MySQL или Mock-объект для тестов, не меняя ни строчки в Сервисе.
SOLID - это фильтр. Прежде чем закоммитить код, спросите себя:
1. Не делает ли мой класс слишком много? (S)
2. Придется ли мне переписывать этот класс, если добавятся новые условия? (O)
3. Не ломаю ли я поведение родителя? (L)
4. Не заставляю ли я других реализовывать ненужные методы? (I)
5. Завишу ли я от интерфейсов или от конкретных классов? (D)
#Architecture #SOLID #CleanCode #OODesign
📲 Мы в MAX
👉@BookJava
Почему один проект живет 10 лет и его легко дорабатывать, а другой через полгода превращается в "Legacy", к которому страшно подходить?
Разница в соблюдении принципов SOLID.
Это аббревиатура из 5 правил, сформулированных Робертом Мартином (Дядя Боб). Если вы нарушаете их - ваш код "гниет".
Давайте разберем каждую букву.
1️⃣ S - Single Responsibility Principle (Единственная ответственность)
"У класса должна быть только одна причина для изменения."
⛔ Как делают новички (God Object):
Класс
OrderService делает всё:1. Считает сумму заказа.
2. Сохраняет заказ в БД.
3. Отправляет email клиенту.
4. Генерирует PDF-чек.
Если бизнес попросит изменить формат чека — мы лезем в этот класс. Если поменяется логика БД - опять в него. Риск сломать отправку писем при правке базы данных огромен!
✅ Как надо:
Разбиваем на маленькие классы:
•
OrderCalculator (считает).•
OrderRepository (сохраняет).•
EmailNotificationService (шлет письма).•
PdfGenerator (печатает).OrderService теперь просто дирижер, который вызывает эти компоненты.2️⃣ O - Open-Closed Principle (Открытость/Закрытость)
"Программные сущности должны быть открыты для расширения, но закрыты для модификации."
Это значит: Не меняйте старый рабочий код, чтобы добавить новую фичу.
⛔ Плохо:
У нас есть метод расчета доставки.
if (deliveryType == "DHL") { ... }
else if (deliveryType == "Post") { ... }
// Пришла задача добавить FedEx? Придется лезть сюда и добавлять else if!
✅ Хорошо:
Используем полиморфизм.
interface DeliveryStrategy { void deliver(); }
class DhlDelivery implements DeliveryStrategy { ... }
class PostDelivery implements DeliveryStrategy { ... }
// Нужен FedEx? Просто создаем НОВЫЙ класс, не трогая старые!
class FedExDelivery implements DeliveryStrategy { ... }
3️⃣ L - Liskov Substitution Principle (Принцип подстановки Барбары Лисков)
"Наследники должны без проблем заменять родителей."
Если у вас есть класс
Bird с методом fly(), а вы создали наследника Penguin (Пингвин), который при вызове fly() бросает ошибку (потому что пингвины не летают) - вы нарушили LSP.Суть: Если код работает с базовым классом, он должен работать и с любым его наследником, не зная об этом и не ломаясь.
4️⃣ I - Interface Segregation Principle (Разделение интерфейсов)
"Много маленьких интерфейсов лучше, чем один огромный."
⛔ Плохо:
Интерфейс
Worker имеет методы work() и eat().Мы создаем класс
Robot. Роботы работают, но не едят.Нам придется реализовать метод
eat() и оставить его пустым или кинуть ошибку. Это мусор.✅ Хорошо:
Разбейте на
Workable и Eatable.Человек имплементирует оба. Робот - только
Workable.5️⃣ D - Dependency Inversion Principle (Инверсия зависимостей)
"Зависьте от абстракций, а не от конкретики."
Это то, что мы учили в Spring (DI).
Ваш
Service не должен зависеть от PostgresRepository. Он должен зависеть от интерфейса Repository.Тогда вы сможете легко подменить Postgres на MySQL или Mock-объект для тестов, не меняя ни строчки в Сервисе.
SOLID - это фильтр. Прежде чем закоммитить код, спросите себя:
1. Не делает ли мой класс слишком много? (S)
2. Придется ли мне переписывать этот класс, если добавятся новые условия? (O)
3. Не ломаю ли я поведение родителя? (L)
4. Не заставляю ли я других реализовывать ненужные методы? (I)
5. Завишу ли я от интерфейсов или от конкретных классов? (D)
#Architecture #SOLID #CleanCode #OODesign
📲 Мы в MAX
👉@BookJava
👍13❤5🔥3
🏗 Порождающие паттерны: Как рождаются объекты?
Создать объект просто:
А если у объекта 20 полей? А если нам нужен только один экземпляр на всё приложение? А если мы не знаем заранее, какой именно класс нам нужен?
Тут на сцену выходят паттерны.
1️⃣ Singleton (Одиночка)
Суть: Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
Где нужен: Логгеры, Конфигурация, Пул соединений с БД.
Как реализовать:
1. Скрываем конструктор (
2. Создаем статическое поле с экземпляром.
3. Возвращаем его через статический метод.
⚠️ Важно: В Spring Boot все бины по умолчанию - синглтоны. Вам не нужно писать этот код руками, контейнер Spring сам следит, чтобы сервис был создан один раз.
2️⃣ Builder (Строитель)
Суть: Позволяет создавать сложные объекты пошагово. Спасает от «Телескопического конструктора» (когда у вас конструктор с 10 аргументами, и вы не помните, где там
Было (Ужас):
Стало (Builder):
🛠 Лайфхак:
В Java не нужно писать Билдер руками (это 50 строк кода). Просто поставьте аннотацию Lombok
3️⃣ Factory Method (Фабричный метод)
Суть: Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
Это реализация принципа Open-Closed. Мы добавляем новые типы продуктов, не ломая существующий код.
Пример: У нас есть "Уведомления". Сегодня это Email, завтра SMS, послезавтра Push.
🔥 Итог
1. Singleton - когда нужен один объект на всю систему.
2. Builder - когда объект сложный и у него много параметров.
3. Factory - когда мы не знаем заранее, какой конкретно объект понадобится, или хотим скрыть логику выбора.
#DesignPatterns #GoF #Singleton #Builder #Factory #Java
📲 Мы в MAX
👉@BookJava
Создать объект просто:
User u = new User().А если у объекта 20 полей? А если нам нужен только один экземпляр на всё приложение? А если мы не знаем заранее, какой именно класс нам нужен?
Тут на сцену выходят паттерны.
1️⃣ Singleton (Одиночка)
Суть: Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
Где нужен: Логгеры, Конфигурация, Пул соединений с БД.
Как реализовать:
1. Скрываем конструктор (
private).2. Создаем статическое поле с экземпляром.
3. Возвращаем его через статический метод.
public class Database {
// Единственный экземпляр
private static Database instance;
private Database() {} // Никто не создаст объект извне
public static synchronized Database getInstance() {
if (instance == null) {
instance = new Database();
}
return instance;
}
}
⚠️ Важно: В Spring Boot все бины по умолчанию - синглтоны. Вам не нужно писать этот код руками, контейнер Spring сам следит, чтобы сервис был создан один раз.
2️⃣ Builder (Строитель)
Суть: Позволяет создавать сложные объекты пошагово. Спасает от «Телескопического конструктора» (когда у вас конструктор с 10 аргументами, и вы не помните, где там
age, а где height).Было (Ужас):
new User("Alex", null, true, "admin", 25, null);Стало (Builder):
User user = User.builder()
.name("Alex")
.age(25)
.role("ADMIN")
.active(true)
.build();
🛠 Лайфхак:
В Java не нужно писать Билдер руками (это 50 строк кода). Просто поставьте аннотацию Lombok
@Builder над классом.3️⃣ Factory Method (Фабричный метод)
Суть: Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
Это реализация принципа Open-Closed. Мы добавляем новые типы продуктов, не ломая существующий код.
Пример: У нас есть "Уведомления". Сегодня это Email, завтра SMS, послезавтра Push.
// 1. Интерфейс
interface Notification { void send(String msg); }
// 2. Реализации
class EmailNotification implements Notification { ... }
class SmsNotification implements Notification { ... }
// 3. Фабрика (Решает, что создать)
class NotificationFactory {
public static Notification create(String type) {
return switch (type) {
case "EMAIL" -> new EmailNotification();
case "SMS" -> new SmsNotification();
default -> throw new IllegalArgumentException("Unknown type");
};
}
}
// Клиентский код (не знает про классы Email/Sms, знает только интерфейс)
Notification notification = NotificationFactory.create("SMS");
notification.send("Hello!");
🔥 Итог
1. Singleton - когда нужен один объект на всю систему.
2. Builder - когда объект сложный и у него много параметров.
3. Factory - когда мы не знаем заранее, какой конкретно объект понадобится, или хотим скрыть логику выбора.
#DesignPatterns #GoF #Singleton #Builder #Factory #Java
📲 Мы в MAX
👉@BookJava
👍5🔥3
11 февраля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Сергею
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
🏗 Структурные паттерны: Адаптер, Декоратор, Прокси
Когда вы пытаетесь соединить старую библиотеку с новым кодом или добавить логирование, не переписывая половину проекта - вы используете эти паттерны.
🔌 1. Adapter (Адаптер)
Суть: Делает несовместимые интерфейсы совместимыми.
Это как переходник для розетки. У вас вилка американская, а розетка европейская. Адаптер позволяет им работать вместе.
Где нужен: Когда есть старый класс (Legacy), который нельзя менять, но его нужно использовать в новом коде.
Пример: У нас есть система, которая понимает только
🎁 2. Decorator (Декоратор/Обертка)
Суть: Динамически добавляет объекту новые обязанности (функционал).
Это альтернатива наследованию. Вместо того чтобы создавать
Принцип: Матрешка. Каждый декоратор делает свою работу и вызывает следующий.
Пример:
Важно: В
🛡️ 3. Proxy (Заместитель)
Суть: Объект-прокладка, который контролирует доступ к другому объекту.
Клиент думает, что общается с реальным объектом, а на самом деле говорит с его заместителем.
Зачем?
1. Ленивая загрузка (Lazy Loading): Не грузить тяжелую картинку/БД, пока ее реально не попросят.
2. Безопасность: Проверить права доступа перед выполнением метода.
3. Логирование: Записать "Метод вызван" и передать вызов дальше.
Пример:
Spring Magic: Весь Spring держится на Прокси! Когда вы ставите
🔥 Итог
🔴 Adapter - меняет интерфейс объекта (чтобы подошел).
🔴 Decorator - меняет поведение объекта (добавляет фичи), не меняя интерфейс.
🔴 Proxy - контролирует доступ к объекту (ленивость, защита).
#DesignPatterns #Adapter #Decorator #Proxy #Architecture
📲 Мы в MAX
👉@BookJava
Когда вы пытаетесь соединить старую библиотеку с новым кодом или добавить логирование, не переписывая половину проекта - вы используете эти паттерны.
🔌 1. Adapter (Адаптер)
Суть: Делает несовместимые интерфейсы совместимыми.
Это как переходник для розетки. У вас вилка американская, а розетка европейская. Адаптер позволяет им работать вместе.
Где нужен: Когда есть старый класс (Legacy), который нельзя менять, но его нужно использовать в новом коде.
Пример: У нас есть система, которая понимает только
KM/H (километры), а внешняя библиотека выдает скорость в MPH (мили).
// 1. Наш интерфейс (чего мы ждем)
interface Movable { double getSpeed(); } // км/ч
// 2. Чужой класс (что есть)
class Bugatti {
double getSpeedMph() { return 268; }
}
// 3. Адаптер (Переводчик)
class MovableAdapter implements Movable {
private Bugatti bugatti;
public MovableAdapter(Bugatti bugatti) {
this.bugatti = bugatti;
}
@Override
public double getSpeed() {
return convertMphToKmph(bugatti.getSpeedMph());
}
}
🎁 2. Decorator (Декоратор/Обертка)
Суть: Динамически добавляет объекту новые обязанности (функционал).
Это альтернатива наследованию. Вместо того чтобы создавать
CoffeeWithMilkAndSugar, мы берем Coffee и заворачиваем его в Milk, а потом в Sugar.Принцип: Матрешка. Каждый декоратор делает свою работу и вызывает следующий.
Пример:
// Базовый кофе
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getCost()); // 10$
// Добавили молоко (Обернули)
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getCost()); // 12$
// Добавили сахар (Обернули еще раз)
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getCost()); // 13$
Важно: В
java.io это используется повсюду: new BufferedReader(new FileReader(file)).🛡️ 3. Proxy (Заместитель)
Суть: Объект-прокладка, который контролирует доступ к другому объекту.
Клиент думает, что общается с реальным объектом, а на самом деле говорит с его заместителем.
Зачем?
1. Ленивая загрузка (Lazy Loading): Не грузить тяжелую картинку/БД, пока ее реально не попросят.
2. Безопасность: Проверить права доступа перед выполнением метода.
3. Логирование: Записать "Метод вызван" и передать вызов дальше.
Пример:
interface Image { void display(); }
class RealImage implements Image {
public RealImage(String file) { loadFromDisk(file); } // Долгая операция!
public void display() { System.out.println("Displaying..."); }
}
class ProxyImage implements Image {
private RealImage realImage;
private String file;
public ProxyImage(String file) { this.file = file; }
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(file); // Грузим только сейчас!
}
realImage.display();
}
}
Spring Magic: Весь Spring держится на Прокси! Когда вы ставите
@Transactional, Spring создает прокси вокруг вашего сервиса, открывает транзакцию, вызывает ваш метод, а потом закрывает транзакцию.🔥 Итог
#DesignPatterns #Adapter #Decorator #Proxy #Architecture
📲 Мы в MAX
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🎥 Открытый урок «Class Data Sharing и его перспективы».
🗓 17 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Advanced».
Что будет на вебинаре:
✔️ Назначение Class Data Sharing.
✔️ Поддержка и использование в Spring Boot.
✔️ Разница с Native Image для GraalVM.
В результате вебинара:
Сможете запустить Spring Boot-приложение с использованием CDS и понять базовую настройку. Получите представление, чем CDS отличается от Native Image (GraalVM).
Кому будет интересно:
Подойдёт Java-разработчикам и инженерам, которым важно ускорить старт сервисов и оптимизировать время запуска в проде.
🔗 Ссылка на регистрацию: https://vk.cc/cUiTYA
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🗓 17 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Advanced».
Быстрый, лёгкий старт Java-сервисов — конкурентное преимущество. Разберём, чем поможет Class Data Sharing и где он уместен.
Что будет на вебинаре:
В результате вебинара:
Сможете запустить Spring Boot-приложение с использованием CDS и понять базовую настройку. Получите представление, чем CDS отличается от Native Image (GraalVM).
Кому будет интересно:
Подойдёт Java-разработчикам и инженерам, которым важно ускорить старт сервисов и оптимизировать время запуска в проде.
🔗 Ссылка на регистрацию: https://vk.cc/cUiTYA
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🧠 Поведенческие паттерны: Стратегия, Наблюдатель, Цепочка
Эти паттерны помогают избежать спагетти-кода, где один класс управляет всем миром через гигантские
🗺 1. Strategy (Стратегия)
Суть: Позволяет менять алгоритм поведения объекта прямо "на лету", во время выполнения программы.
Это убийца бесконечных
Аналогия: Навигатор. Вы строите маршрут из точки А в точку Б. Стратегия - это способ передвижения:
🔴 Пешком (один алгоритм).
🔴 На машине (другой алгоритм).
🔴 На автобусе (третий алгоритм).
Цель одна, пути реализации разные.
Код:
👀 2. Observer (Наблюдатель / Listener)
Суть: Один объект (Subject) меняет свое состояние, и все зависимые от него объекты (Observers) тут же узнают об этом.
Аналогия: YouTube-канал.
🔴 Блогер (Subject) выпускает видео.
🔴 Подписчики (Observers) получают уведомление.
🔴 Если вы отписались - уведомления приходить перестанут.
Код: Это основа всех UI-фреймворков (кнопка нажата -> слушатель сработал) и даже архитектуры Kafka.
🔗 3. Chain of Responsibility (Цепочка обязанностей)
Суть: Запрос передается по цепочке обработчиков. Каждый обработчик решает: обработать запрос самому или передать следующему.
Аналогия: Техподдержка.
1. Сначала отвечает Чат-бот (Уровень 1). Не справился? -> Передает дальше.
2. Оператор колл-центра (Уровень 2). Не справился? -> Передает дальше.
3. Инженер (Уровень 3). Решает проблему.
Пример в Spring:
Spring Security работает именно так! Ваш HTTP-запрос проходит через цепочку фильтров:
🔴
Если хоть один фильтр скажет "Нет", запрос дальше не пойдет.
Код:
🔥 Итог
🔴 Strategy - Выбираем алгоритм действия (Платим картой или кэшем?).
🔴 Observer - Слушаем изменения (Вышло видео -> пришло уведомление).
🔴 Chain of Responsibility - Передаем эстафету (Фильтр 1 -> Фильтр 2 -> Контроллер).
#DesignPatterns #Behavioral #Strategy #Observer #ChainOfResponsibility
📲 Мы в MAX
👉@BookJava
Эти паттерны помогают избежать спагетти-кода, где один класс управляет всем миром через гигантские
if-else.🗺 1. Strategy (Стратегия)
Суть: Позволяет менять алгоритм поведения объекта прямо "на лету", во время выполнения программы.
Это убийца бесконечных
if (type == "CARD") { ... } else if (type == "PAYPAL") { ... }.Аналогия: Навигатор. Вы строите маршрут из точки А в точку Б. Стратегия - это способ передвижения:
Цель одна, пути реализации разные.
Код:
// Общий интерфейс
interface RouteStrategy {
void buildRoute(String a, String b);
}
// Конкретные стратегии
class RoadStrategy implements RouteStrategy { ... }
class WalkingStrategy implements RouteStrategy { ... }
// Контекст (Навигатор)
class Navigator {
private RouteStrategy strategy;
public void setStrategy(RouteStrategy strategy) {
this.strategy = strategy; // Меняем на лету!
}
public void buildRoute(String a, String b) {
strategy.buildRoute(a, b);
}
}
👀 2. Observer (Наблюдатель / Listener)
Суть: Один объект (Subject) меняет свое состояние, и все зависимые от него объекты (Observers) тут же узнают об этом.
Аналогия: YouTube-канал.
Код: Это основа всех UI-фреймворков (кнопка нажата -> слушатель сработал) и даже архитектуры Kafka.
class NewsAgency {
private List<Channel> channels = new ArrayList<>();
public void subscribe(Channel channel) {
channels.add(channel);
}
public void broadcast(String news) {
for (Channel channel : channels) {
channel.update(news); // Уведомляем всех!
}
}
}
🔗 3. Chain of Responsibility (Цепочка обязанностей)
Суть: Запрос передается по цепочке обработчиков. Каждый обработчик решает: обработать запрос самому или передать следующему.
Аналогия: Техподдержка.
1. Сначала отвечает Чат-бот (Уровень 1). Не справился? -> Передает дальше.
2. Оператор колл-центра (Уровень 2). Не справился? -> Передает дальше.
3. Инженер (Уровень 3). Решает проблему.
Пример в Spring:
Spring Security работает именно так! Ваш HTTP-запрос проходит через цепочку фильтров:
CorsFilter (проверяет домен) -> JwtFilter (проверяет токен) -> UsernamePasswordFilter (проверяет логин).Если хоть один фильтр скажет "Нет", запрос дальше не пойдет.
Код:
abstract class SupportHandler {
protected SupportHandler next;
public void setNext(SupportHandler next) { this.next = next; }
public void handleRequest(String issue) {
if (canHandle(issue)) {
solve();
} else if (next != null) {
next.handleRequest(issue); // Передаем следующему
}
}
}
🔥 Итог
#DesignPatterns #Behavioral #Strategy #Observer #ChainOfResponsibility
📲 Мы в MAX
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🧅 Архитектура: От Слоев к Луковице
❌ Проблема Слоенки (Database Driven Design)
В классическом Spring-приложении зависимости идут сверху вниз:
1. Контроллер зависит от Сервиса.
2. Сервис зависит от Репозитория (Базы данных).
В чем подвох?
Ваша бизнес-логика (Сервис) намертво привязана к деталям хранения данных (БД).
🔴 Хотите поменять SQL на NoSQL? Переписывайте сервис.
🔴 Хотите протестировать логику? Придется мокать базу данных.
🔴 Главный грех: База данных диктует, как писать бизнес-логику. А должно быть наоборот!
✅ Решение: Clean / Hexagonal / Onion
Дядя Боб, Алистер Кокберн и другие умные дядьки придумали, как перевернуть игру.
Главная идея: Зависимости должны быть направлены ТОЛЬКО внутрь, к центру.
Представьте приложение как Луковицу.
1. Ядро (Core / Domain) - Центр Вселенной
Здесь живет ваша Бизнес-логика.
🔴 Сущности (
🔴 Правила (
🔴 Правило: Здесь НЕТ фреймворков. Никакого Spring, никакого Hibernate, никакого SQL. Только чистая Java.
🔴 Этот слой ничего не знает о внешнем мире.
2. Порты (Ports / Use Cases) - Граница
Ядро определяет интерфейсы (Порты), которые ему нужны для работы.
🔴 Например:
🔴 Заметьте: интерфейс лежит внутри домена!
3. Адаптеры (Adapters / Infrastructure) - Внешний мир
Здесь живут детали реализации.
🔴
🔴
🔴 Здесь подключается Spring, Hibernate, Kafka и всё остальное.
🔄 Инверсия Зависимостей (DIP)
Следите за руками:
1. В слоеной архитектуре:
2. В чистой архитектуре:
Оба зависят от абстракции. БД стала просто плагином. Вы можете выкинуть Postgres и поставить заглушку (In-Memory Map) - и бизнес-логика даже не заметит подмены!
⚖️ Когда что использовать?
1. Layered (Controller-Service-Repo)
• ✅ Простые CRUD-приложения.
• ✅ Админки, прототипы.
• ✅ Когда логики почти нет, просто перекладываем данные.
2. Hexagonal (Ports & Adapters)
• ✅ Сложная бизнес-логика (Банкинг, Финтех, Логистика).
• ✅ Приложение живет долго (5+ лет).
• ✅ Нужно писать много Unit-тестов для ядра, не поднимая контекст Spring.
🔥 Итог
🔴 Layered: Быстро писать, сложно поддерживать. БД - главная.
🔴 Clean: Дольше писать (много маппингов DTO <-> Entity), легко поддерживать. Логика - главная.
#Architecture #CleanArchitecture #Hexagonal #Spring #Java
📲 Мы в MAX
👉@BookJava
❌ Проблема Слоенки (Database Driven Design)
В классическом Spring-приложении зависимости идут сверху вниз:
1. Контроллер зависит от Сервиса.
2. Сервис зависит от Репозитория (Базы данных).
В чем подвох?
Ваша бизнес-логика (Сервис) намертво привязана к деталям хранения данных (БД).
✅ Решение: Clean / Hexagonal / Onion
Дядя Боб, Алистер Кокберн и другие умные дядьки придумали, как перевернуть игру.
Главная идея: Зависимости должны быть направлены ТОЛЬКО внутрь, к центру.
Представьте приложение как Луковицу.
1. Ядро (Core / Domain) - Центр Вселенной
Здесь живет ваша Бизнес-логика.
User, Order).User не может быть моложе 18 лет).2. Порты (Ports / Use Cases) - Граница
Ядро определяет интерфейсы (Порты), которые ему нужны для работы.
interface UserRepository (найти пользователя, сохранить пользователя).3. Адаптеры (Adapters / Infrastructure) - Внешний мир
Здесь живут детали реализации.
PostgresUserRepository реализует интерфейс UserRepository.RestController вызывает методы Ядра.🔄 Инверсия Зависимостей (DIP)
Следите за руками:
1. В слоеной архитектуре:
Service зависит от PostgresDao.2. В чистой архитектуре:
Service зависит от Интерфейса. А PostgresDao зависит от Интерфейса.Оба зависят от абстракции. БД стала просто плагином. Вы можете выкинуть Postgres и поставить заглушку (In-Memory Map) - и бизнес-логика даже не заметит подмены!
⚖️ Когда что использовать?
1. Layered (Controller-Service-Repo)
• ✅ Простые CRUD-приложения.
• ✅ Админки, прототипы.
• ✅ Когда логики почти нет, просто перекладываем данные.
2. Hexagonal (Ports & Adapters)
• ✅ Сложная бизнес-логика (Банкинг, Финтех, Логистика).
• ✅ Приложение живет долго (5+ лет).
• ✅ Нужно писать много Unit-тестов для ядра, не поднимая контекст Spring.
🔥 Итог
#Architecture #CleanArchitecture #Hexagonal #Spring #Java
📲 Мы в MAX
👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2