Please open Telegram to view this post
VIEW IN TELEGRAM
😢19💯8❤2😁1
Открывается через Run → Evaluate Expression или Alt + F8 (Option + F8 на macOS).
🔹 Что это вообще такое
Небольшое окно с полем ввода, в котором можно написать любое Java-выражение и мгновенно получить результат. Код выполняется в контексте текущего фрейма — видны все локальные переменные, this, поля класса.
🔹 Примеры из реальной жизни
▪️ Вызов метода на живом объекте
userService.findById(42L)
Не нужно писать тест — просто вызываете метод и смотрите, что он реально вернёт с текущими данными в БД.
▪️ Проверка сложного условия
order.getItems().stream()
.anyMatch(i -> i.getPrice().compareTo(BigDecimal.ZERO) < 0)
Подозреваете, что в заказе есть товары с отрицательной ценой? Проверяете прямо сейчас, не добавляя логов.
▪️ Изменение переменной на лету
user.setRole(Role.ADMIN)
Хотите проверить, как поведёт себя код с другим значением — меняете стейт прямо в памяти и продолжаете выполнение. Приложение не перезапускается.
▪️ Десериализация или парсинг
objectMapper.writeValueAsString(response)
Получаете красивый JSON из объекта прямо в дебаггере — удобно проверить, что именно уйдёт клиенту.
🔹 Продвинутые трюки
— В окне Evaluate есть переключатель с однострочного режима на Code Fragment — там можно писать многострочный код с переменными, условиями и циклами.
— Результат вычисления отображается как обычная переменная в дереве дебаггера. Можно раскрыть, посмотреть вложенные поля, скопировать значение.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤4👏1
Forwarded from Библиотека собеса по Java | вопросы с собеседований
Memory leak, который живёт неделями и не воспроизводится локально 👇
📦 Задание — code review
Написали фильтр для аудита запросов. В продакшне через несколько дней — OutOfMemoryError.
@Component
public class AuditFilter implements Filter {
private static final ThreadLocal<AuditContext> CONTEXT =
new ThreadLocal<>();
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
AuditContext ctx = new AuditContext(
((HttpServletRequest) request).getRequestURI(),
System.currentTimeMillis()
);
CONTEXT.set(ctx);
try {
chain.doFilter(request, response);
} finally {
auditLog(CONTEXT.get());
}
}
public static AuditContext current() {
return CONTEXT.get();
}
private void auditLog(AuditContext ctx) {
// пишем в БД...
}
}
▪️ Объясни
— Почему объекты в ThreadLocal не собираются GC, даже если запрос завершён.
— Какая одна строчка кода здесь отсутствует, и где именно она должна быть.
* Есть ли риски при использовании ThreadLocal в virtual threads (Project Loom)?
Ставьте → 🔥, если нравится формат. Если нет → 🌚
#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍2❤1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁20💯2😢1👾1
🧵 GC: как выбрать сборщик мусора и не пожалеть
Выбирал ли ты GC хоть раз осознанно? Часто запустил приложение — работает, и ладно. Но когда начинаются проблемы с латентностью или throughput, первый вопрос от SRE: «А какой у вас GC?».
🔹 Разберём что выбрать и почему.
Все GC балансируют между двумя вещами:
▪️ Throughput — сколько полезной работы делает приложение за единицу времени
▪️ Latency — насколько долго приложение паузится на GC
Идеального нет. Выбор всегда зависит от профиля нагрузки.
🔹 Serial и Parallel — если латентность не важна
Serial GC однопоточный. И Minor, и Major GC выполняет один поток, всё приложение стоит. Звучит как антиквариат, но на маленьком heap (< 256MB) и однопоточной среде накладные расходы на координацию потоков не нужны, Serial реально быстрее.
Parallel GC — то же самое, но сборку делают несколько потоков одновременно. STW никуда не девается, просто сама пауза короче за счёт параллелизма. На Major GC всё равно можешь получить сотни миллисекунд.
Где уместно: batch-обработка, утилиты, CLI-инструменты. Там где важен максимальный throughput и никто не ждёт response time.
🔹 G1 — дефолт с Java 9
G1 делит heap на регионы фиксированного размера (~1-32MB) и собирает их инкрементально. Не нужно собирать весь heap за раз — выбираются регионы с наибольшим количеством мусора (отсюда "Garbage First").
Главная настройка:
Это не гарантия, это цель. G1 будет подстраивать размер собираемых регионов, чтобы уложиться.
Где уместно: большинство серверных приложений с heap от 4GB. Хороший баланс throughput/latency без тюнинга.
🔹 ZGC и Shenandoah — когда паузы недопустимы
Оба делают большую часть работы конкурентно — параллельно с работой приложения. STW-паузы измеряются единицами миллисекунд вне зависимости от размера heap.
Где уместно: real-time системы, trading, API с жёсткими SLA по p99 латентности. Платишь немного throughput — получаешь предсказуемые паузы.
🔹 Как выбирать на практике
Не угадывать, а мерить. Включаешь GC логи и смотришь что происходит:
Дальше либо GCEasy, либо руками смотришь на паузы и частоту сборок.
🔹 Три вопроса которые определяют выбор
1. Какой размер heap?
До 4GB — G1 справится. Больше 16GB — смотри на ZGC, у G1 начинаются долгие Mixed GC.
2. Какие требования к латентности?
Есть SLA на p99 < 50ms — только ZGC или Shenandoah. Нет жёстких требований — G1.
3. Какой профиль аллокаций?
Много short-lived объектов — генерационный GC справится хорошо. Много long-lived крупных объектов — G1 может давать длинные паузы на evacuation, ZGC справится лучше.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava
Выбирал ли ты GC хоть раз осознанно? Часто запустил приложение — работает, и ладно. Но когда начинаются проблемы с латентностью или throughput, первый вопрос от SRE: «А какой у вас GC?».
🔹 Разберём что выбрать и почему.
Все GC балансируют между двумя вещами:
▪️ Throughput — сколько полезной работы делает приложение за единицу времени
▪️ Latency — насколько долго приложение паузится на GC
Идеального нет. Выбор всегда зависит от профиля нагрузки.
🔹 Serial и Parallel — если латентность не важна
-XX:+UseSerialGC / -XX:+UseParallelGC
Serial GC однопоточный. И Minor, и Major GC выполняет один поток, всё приложение стоит. Звучит как антиквариат, но на маленьком heap (< 256MB) и однопоточной среде накладные расходы на координацию потоков не нужны, Serial реально быстрее.
Parallel GC — то же самое, но сборку делают несколько потоков одновременно. STW никуда не девается, просто сама пауза короче за счёт параллелизма. На Major GC всё равно можешь получить сотни миллисекунд.
Где уместно: batch-обработка, утилиты, CLI-инструменты. Там где важен максимальный throughput и никто не ждёт response time.
🔹 G1 — дефолт с Java 9
-XX:+UseG1GC
G1 делит heap на регионы фиксированного размера (~1-32MB) и собирает их инкрементально. Не нужно собирать весь heap за раз — выбираются регионы с наибольшим количеством мусора (отсюда "Garbage First").
Главная настройка:
bash-XX:MaxGCPauseMillis=200 # целевое время паузы
Это не гарантия, это цель. G1 будет подстраивать размер собираемых регионов, чтобы уложиться.
Где уместно: большинство серверных приложений с heap от 4GB. Хороший баланс throughput/latency без тюнинга.
🔹 ZGC и Shenandoah — когда паузы недопустимы
-XX:+UseZGC / -XX:+UseShenandoahGC
Оба делают большую часть работы конкурентно — параллельно с работой приложения. STW-паузы измеряются единицами миллисекунд вне зависимости от размера heap.
Где уместно: real-time системы, trading, API с жёсткими SLA по p99 латентности. Платишь немного throughput — получаешь предсказуемые паузы.
🔹 Как выбирать на практике
Не угадывать, а мерить. Включаешь GC логи и смотришь что происходит:
bash-Xlog:gc*:file=gc.log:time,uptime:filecount=5,filesize=20m
Дальше либо GCEasy, либо руками смотришь на паузы и частоту сборок.
🔹 Три вопроса которые определяют выбор
1. Какой размер heap?
До 4GB — G1 справится. Больше 16GB — смотри на ZGC, у G1 начинаются долгие Mixed GC.
2. Какие требования к латентности?
Есть SLA на p99 < 50ms — только ZGC или Shenandoah. Нет жёстких требований — G1.
3. Какой профиль аллокаций?
Много short-lived объектов — генерационный GC справится хорошо. Много long-lived крупных объектов — G1 может давать длинные паузы на evacuation, ZGC справится лучше.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3🔥1
Вышла Java 25, которую все хотят попробовать. Но ставить ли её или взять проверенную Java 21 LTS?
В этом гайде — пошаговая установка Java на Windows с картинками, разбор различий между версиями, настройка JAVA_HOME и PATH.
Ориентирован для начинающих разработчиков, изучающих Java
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁28💯2🔥1
🎁 Паттерн Decorator
Decorator — структурный паттерн, который добавляет объектам новое поведение, оборачивая их в объекты-обёртки. Альтернатива наследованию, когда комбинаций поведения много и они меняются в рантайме.
Использование
🔹 Когда нужно добавить поведение объекту, не меняя его класс и не трогая остальные объекты.
🔹 Когда наследование порождает взрывной рост классов из-за комбинаций поведений.
🔹 Когда поведение нужно добавлять и убирать динамически в рантайме.
Преимущества
1️⃣ Гибкость комбинирования поведений
Каждый декоратор делает одно дело. Нужно кеширование + логирование + метрики? Оборачиваете в три слоя в любом порядке. Не нужны метрики — просто не добавляете этот слой.
2️⃣ Единая ответственность
Кеширование живёт в одном классе, логирование — в другом. Каждый декоратор легко читать, тестировать и заменять независимо.
3️⃣ Прозрачность для клиента
Декоратор реализует тот же интерфейс, что и оригинал. Клиентский код не знает, с чем работает — с оригиналом или с обёрткой.
⚠️ Порядок декораторов имеет значение. Метрики снаружи кеша видят кеш-хиты корректно. Метрики внутри — не видят их вообще.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava
Decorator — структурный паттерн, который добавляет объектам новое поведение, оборачивая их в объекты-обёртки. Альтернатива наследованию, когда комбинаций поведения много и они меняются в рантайме.
Использование
🔹 Когда нужно добавить поведение объекту, не меняя его класс и не трогая остальные объекты.
🔹 Когда наследование порождает взрывной рост классов из-за комбинаций поведений.
🔹 Когда поведение нужно добавлять и убирать динамически в рантайме.
Преимущества
Каждый декоратор делает одно дело. Нужно кеширование + логирование + метрики? Оборачиваете в три слоя в любом порядке. Не нужны метрики — просто не добавляете этот слой.
Кеширование живёт в одном классе, логирование — в другом. Каждый декоратор легко читать, тестировать и заменять независимо.
Декоратор реализует тот же интерфейс, что и оригинал. Клиентский код не знает, с чем работает — с оригиналом или с обёрткой.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Java-разработчик Middle - от 200 000 до 250 000 ₽ - гибрид (Новосибирск)
Java-разработчик - от 280 000 ₽ - удалёнка
Tech Lead (Java / Spark) - 400 000 ₽ - офис (Москва)
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
✌🏻 У нас две новости — хорошая и плохая!
Хорошая: Ваших знаний, скорее всего, хватит, чтобы собрать рабочую демку AI-агента в Colab. 🫡
Плохая: Вы вряд ли выведете его в прод, не обанкротившись на токенах и не слив базу. 🤯
Для защиты от таких сценариев мы полностью пересобрали курс «Разработка AI-агентов». Теперь внутри плотная работа с экономикой ресурсов, дебаг через time-travel в
Программа курса, полный состав спикеров и другие подробности 👈🏻
ВАЖНО! До 5 апреля на курс действует скидка, но свободные места могут закончиться раньше.
Хорошая: Ваших знаний, скорее всего, хватит, чтобы собрать рабочую демку AI-агента в Colab. 🫡
Плохая: Вы вряд ли выведете его в прод, не обанкротившись на токенах и не слив базу. 🤯
Для защиты от таких сценариев мы полностью пересобрали курс «Разработка AI-агентов». Теперь внутри плотная работа с экономикой ресурсов, дебаг через time-travel в
LangGraph, извлечение данных из кривых сканов для RAG и комплаенс по 152-ФЗ.Если всё ещё сомневаетесь, послушайте голосовое от спикера курса Влада Прошинского, где он объясняет, как правильно тестировать агентов перед релизом.
Программа курса, полный состав спикеров и другие подробности 👈🏻
ВАЖНО! До 5 апреля на курс действует скидка, но свободные места могут закончиться раньше.
🥱4
📨 Transactional Outbox c AI
Сценарий: сохранил сущность, опубликовал событие в Kafka, транзакция откатилась — событие уже ушло. Или наоборот: транзакция прошла, Kafka недоступна — событие потеряно.
Outbox Pattern решает это на уровне архитектуры. Промпт:
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Сценарий: сохранил сущность, опубликовал событие в Kafka, транзакция откатилась — событие уже ушло. Или наоборот: транзакция прошла, Kafka недоступна — событие потеряно.
Outbox Pattern решает это на уровне архитектуры. Промпт:
Ты Senior Java-разработчик. Сгенерируй реализацию Transactional Outbox Pattern для Spring Boot.
Требования:
- Сущность OutboxEvent: id (UUID), aggregateType, aggregateId, eventType,
payload (JSONB), createdAt, processedAt, status (PENDING/PROCESSED/FAILED)
- OutboxEventPublisher: сохраняет событие в той же транзакции что и бизнес-данные
- OutboxPoller: @Scheduled, читает PENDING-события, публикует в Kafka
- SELECT FOR UPDATE SKIP LOCKED при выборке — объясни зачем в комментарии
- @Transactional(propagation = REQUIRES_NEW) на polling-методе
- Flyway-миграция для таблицы
Стек: Java 21, Spring Boot 3.2, Spring Kafka, PostgreSQL, Flyway
Верни код сущности, репозитория, сервисов, SQL-миграцию, конфиг Kafka.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
2🥱10❤3👍1👾1
Forwarded from Библиотека собеса по Java | вопросы с собеседований
Код чистый, тесты быстрые, на реальных данных — pg_stat_activity в огне 👇
📦 Задание — code review
Ручка возвращает список заказов с информацией о товарах. Работает корректно, но DBA прибежал с графиком: каждый вызов делает тысячи запросов к БД.
@Entity
public class Order {
@Id
private Long id;
private Long userId;
private LocalDateTime createdAt;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
private List<OrderItem> items;
}
@Entity
public class OrderItem {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Order order;
@ManyToOne(fetch = FetchType.LAZY)
private Product product;
private Integer quantity;
}
@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderRepository orderRepository;
@GetMapping("/orders")
public List<OrderDto> getOrders(@RequestParam Long userId) {
List<Order> orders = orderRepository.findByUserId(userId);
return orders.stream()
.map(order -> new OrderDto(
order.getId(),
order.getItems().stream()
.map(item -> new ItemDto(
item.getProduct().getName(),
item.getQuantity()
))
.toList()
))
.toList();
}
}
▪️ Объясни
— Точную механику N+1: где и сколько раз запросы уходят в БД в этом коде.
— Почему FetchType.EAGER «решит» проблему, но создаст другую.
— Как можно решить проблему.
Ставьте → 🔥, если нравится формат. Если нет → 🌚
#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20❤5
Please open Telegram to view this post
VIEW IN TELEGRAM
😁21❤2👾2👍1💯1
🐳 Магия Docker CLI
Контейнер запустился, но ведёт себя странно — не то сетевое окружение, не те переменные, непонятно что вообще внутри? Просто запустите docker inspect, и у вас будет полная картина без лишних инструментов.
🔹 Зачем это нужно
— Возвращает полный JSON с внутренностями: переменные окружения, тома, сетевые настройки, лимиты ресурсов, entrypoint, restart policy.
— Работает не только с контейнерами — понимает образы, тома и сети.
— Незаменимо, когда нужно быстро понять, почему контейнер ведёт себя не так, как ожидается.
🔹 Как использовать
— Полный дамп:
— Только IP-адрес:
— Все переменные окружения:
— Смонтированные тома:
Флаг -f принимает Go-шаблоны — вытащите ровно то поле, которое нужно, без парсинга тысячи строк JSON вручную.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Контейнер запустился, но ведёт себя странно — не то сетевое окружение, не те переменные, непонятно что вообще внутри? Просто запустите docker inspect, и у вас будет полная картина без лишних инструментов.
🔹 Зачем это нужно
— Возвращает полный JSON с внутренностями: переменные окружения, тома, сетевые настройки, лимиты ресурсов, entrypoint, restart policy.
— Работает не только с контейнерами — понимает образы, тома и сети.
— Незаменимо, когда нужно быстро понять, почему контейнер ведёт себя не так, как ожидается.
🔹 Как использовать
— Полный дамп:
docker inspect my-container— Только IP-адрес:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container— Все переменные окружения:
docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' my-container— Смонтированные тома:
docker inspect -f '{{json .Mounts}}' my-container | jqФлаг -f принимает Go-шаблоны — вытащите ровно то поле, которое нужно, без парсинга тысячи строк JSON вручную.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁15❤3
🧵 Просто о сложном: Kubernetes
Не DevOps-гайд, не «как установить кластер». Именно то, с чем ты столкнёшься как разработчик когда твой сервис едет в K8s.
🔹 Что куда деплоится
Твой jar живёт в Docker-образе. Образ запускается как Pod — минимальная единица в K8s. Pod эфемерен: упал, рестартовал, переехал на другую ноду — это нормально, это не баг.
Нода — это физическая или виртуальная машина в кластере.
Кластер состоит из нескольких нод, на каждой из них K8s запускает поды. Когда нода падает или уходит на обслуживание — K8s автоматически перезапускает её поды на других нодах.
Как разработчику тебе не нужно знать на какой ноде живёт твой под, K8s сам решает это на основе requests ресурсов.
Чтобы управлять несколькими копиями пода используют Deployment:
requests — сколько K8s резервирует для пода при планировании. limits — жёсткий потолок. Превысил memory limit — OOMKill. Превысил CPU limit — троттлинг.
Это напрямую влияет на JVM: именно от limits.memory нужно считать -XX:MaxRAMPercentage.
🔹 Как сервисы находят друг друга
Pod умирает и поднимается с новым IP. Поэтому обращаться к поду напрямую нельзя. Service — стабильный DNS-адрес и балансировщик поверх набора подов.
Внутри кластера твой payment-service обращается к order-service просто по имени
K8s DNS резолвит это в нужный ClusterIP. Никаких Eureka, никакого Consul — для базового service discovery это не нужно.
🔹 K8s не знает что твой сервис готов
K8s видит что контейнер запустился. Но не знает что Spring контекст поднялся, Liquibase отработал и сервис готов принимать трафик.
Readiness — сервис готов принимать трафик. Пока не прошёл, pod исключается из балансировки Service.
Liveness — сервис живой. Не прошёл несколько раз подряд, pod рестартует. Сюда не стоит вешать проверку зависимостей (БД, кафка) — если БД легла, рестарт сервиса не поможет.
Spring Boot Actuator отдаёт оба эндпоинта из коробки при
🔹 ConfigMap и Secret
Хардкодить урлы и пароли в application.properties внутри образа — плохая идея. Образ должен быть одинаковым для dev, staging и prod.
В Deployment пробрасываешь как env-переменные — Spring Boot подхватывает автоматически через @Value или application.properties биндинг.
Kubernetes не требует от разработчика знания всего кластерного стека. Но понимать как твой сервис деплоится, как K8s решает готов ли он к трафику и как корректно завершает работу — это уже твоя зона ответственности, не DevOps.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava
Не DevOps-гайд, не «как установить кластер». Именно то, с чем ты столкнёшься как разработчик когда твой сервис едет в K8s.
🔹 Что куда деплоится
Твой jar живёт в Docker-образе. Образ запускается как Pod — минимальная единица в K8s. Pod эфемерен: упал, рестартовал, переехал на другую ноду — это нормально, это не баг.
Нода — это физическая или виртуальная машина в кластере.
Кластер состоит из нескольких нод, на каждой из них K8s запускает поды. Когда нода падает или уходит на обслуживание — K8s автоматически перезапускает её поды на других нодах.
Как разработчику тебе не нужно знать на какой ноде живёт твой под, K8s сам решает это на основе requests ресурсов.
Чтобы управлять несколькими копиями пода используют Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
spec:
containers:
- name: order-service
image: order-service:1.4.2
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
requests — сколько K8s резервирует для пода при планировании. limits — жёсткий потолок. Превысил memory limit — OOMKill. Превысил CPU limit — троттлинг.
Это напрямую влияет на JVM: именно от limits.memory нужно считать -XX:MaxRAMPercentage.
🔹 Как сервисы находят друг друга
Pod умирает и поднимается с новым IP. Поэтому обращаться к поду напрямую нельзя. Service — стабильный DNS-адрес и балансировщик поверх набора подов.
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order-service
ports:
- port: 8080
Внутри кластера твой payment-service обращается к order-service просто по имени
K8s DNS резолвит это в нужный ClusterIP. Никаких Eureka, никакого Consul — для базового service discovery это не нужно.
🔹 K8s не знает что твой сервис готов
K8s видит что контейнер запустился. Но не знает что Spring контекст поднялся, Liquibase отработал и сервис готов принимать трафик.
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
Readiness — сервис готов принимать трафик. Пока не прошёл, pod исключается из балансировки Service.
Liveness — сервис живой. Не прошёл несколько раз подряд, pod рестартует. Сюда не стоит вешать проверку зависимостей (БД, кафка) — если БД легла, рестарт сервиса не поможет.
Spring Boot Actuator отдаёт оба эндпоинта из коробки при
management.endpoint.health.probes.enabled=true.🔹 ConfigMap и Secret
Хардкодить урлы и пароли в application.properties внутри образа — плохая идея. Образ должен быть одинаковым для dev, staging и prod.
apiVersion: v1
kind: ConfigMap
metadata:
name: order-service-config
data:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/orders
SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
---
apiVersion: v1
kind: Secret
metadata:
name: order-service-secret
data:
SPRING_DATASOURCE_PASSWORD: cGFzc3dvcmQ= # base64
В Deployment пробрасываешь как env-переменные — Spring Boot подхватывает автоматически через @Value или application.properties биндинг.
Kubernetes не требует от разработчика знания всего кластерного стека. Но понимать как твой сервис деплоится, как K8s решает готов ли он к трафику и как корректно завершает работу — это уже твоя зона ответственности, не DevOps.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥1
Forwarded from Библиотека задач по Java | тесты, код, задания
Что будет результатом кода?
Anonymous Quiz
3%
null
23%
Ошибка компиляции
5%
Shape
59%
Circle
10%
Посмотреть ответ
👍3🥱3🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁22💯5🔥2😢2
👁 Паттерн Observer
Observer — поведенческий паттерн, который создаёт механизм подписки: одни объекты следят за событиями других и реагируют на них. Источник событий не знает, кто именно подписан и что произойдёт.
Использование
🔹 Когда изменение одного объекта должно автоматически обновлять другие — и вы не знаете заранее, сколько их.
🔹 Когда объекты должны уведомлять других без жёсткой связи между ними.
🔹 Когда набор реакций на событие может меняться в рантайме.
Преимущества
1️⃣ Слабая связанность
Источник события ничего не знает о подписчиках — только то, что они реализуют нужный интерфейс. Добавить нового подписчика можно, не трогая источник.
2️⃣ Динамическая подписка
Подписчики добавляются и удаляются в рантайме. Поведение системы меняется без перекомпиляции.
3️⃣ Соответствие принципу Open/Closed.
Новая реакция на событие — новый подписчик. Источник и существующие подписчики не меняются.
⚠️ Утечки памяти. Подписчик, который не отписался — не будет собран GC, пока жив источник.
В Spring: ApplicationEventPublisher + @EventListener — это Observer из коробки. Добавить @Async к слушателю и подписчик изолирован от основного потока.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava
Observer — поведенческий паттерн, который создаёт механизм подписки: одни объекты следят за событиями других и реагируют на них. Источник событий не знает, кто именно подписан и что произойдёт.
Использование
🔹 Когда изменение одного объекта должно автоматически обновлять другие — и вы не знаете заранее, сколько их.
🔹 Когда объекты должны уведомлять других без жёсткой связи между ними.
🔹 Когда набор реакций на событие может меняться в рантайме.
Преимущества
Источник события ничего не знает о подписчиках — только то, что они реализуют нужный интерфейс. Добавить нового подписчика можно, не трогая источник.
Подписчики добавляются и удаляются в рантайме. Поведение системы меняется без перекомпиляции.
Новая реакция на событие — новый подписчик. Источник и существующие подписчики не меняются.
В Spring: ApplicationEventPublisher + @EventListener — это Observer из коробки. Добавить @Async к слушателю и подписчик изолирован от основного потока.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1🔥1