Spring Boot магия, которая на самом деле просто проверка classpath.

@ConditionalOnClass - одна из тех аннотаций, из-за которых Spring Boot кажется умным.

Она говорит фреймворку:

«Включи этот bean или конфигурацию только если нужный класс реально есть в проекте».

Простой пример:


@Configuration
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration
{
// загружается только если доступен javax.sql.DataSource
}


То есть Spring Boot не пытается настраивать всё подряд.

Он смотрит:

• есть ли нужная библиотека в зависимостях
• доступен ли конкретный класс
• можно ли безопасно включить автоконфигурацию

Именно поэтому ты добавляешь starter - и внезапно появляется конфигурация для базы, Redis, Kafka, Web MVC или Security.

Не потому что Spring «угадал».

А потому что нужные классы появились в classpath, и условия автоконфигурации стали true.

В этом и есть главный принцип Spring Boot:

меньше ручной настройки, больше условий, которые включаются только когда проект к ним готов.
👍 4
1
1 9 837
Код на скорости: митап про производительность, ИИ-агенты и бизнес-процессы в Омске! ⚡️

Встречаемся уже 28 мая, чтобы разобраться:

✔️ Как выкрутить на максимум производительность продукта без больших затрат. Спойлер: помогут виртуальные потоки и корутины (можно сделать скрытым текстом).

✔️ Как создать ИИ-агента, который анализирует сбои и борется с мошенничеством.

✔️ Как моделировать процессы в BPMN так, чтобы минимизировать ошибки.

В финале митапа — крутой «мафиозно-квизный» нетворкинг.

Дата: 28 мая в 18:00
Место: Школа 21 (ул. Ленина, д. 26Б)
Регистрация: здесь!
😁 2
1
1 968
N+1 в Spring Boot выглядит безобидно, пока прод не начинает молиться на базу данных.

Классический сценарий:

Вы грузите список заказов:

orderRepository.findAll()

А потом в цикле обращаетесь к order.getItems().

Hibernate сначала делает один запрос за заказами, а потом ещё по одному запросу на каждый заказ, чтобы достать items.

100 заказов = 101 SQL-запрос.

И вот здесь спасает @EntityGraph.

Он позволяет явно сказать репозиторию, какие связи нужно подтянуть сразу:

@EntityGraph(attributePaths = {"items"})

В итоге Hibernate может сгенерировать один запрос с JOIN, вместо десятков лишних походов в базу.

Что получаем:

- меньше SQL-запросов
- меньше нагрузки на БД
- чище код репозитория
- без ручного JPQL
- fetch-стратегия управляется точечно под конкретный кейс

LAZY сам по себе не зло. Зло - когда вы не контролируете, где и как он срабатывает.

@EntityGraph - один из самых простых способов держать N+1 под контролем в Spring Boot.
12
👍 3
👏 1
7 46 2.7K
Твой код — в сердце мощного ИИ! 💚

Команда GigaChat зовёт на One Day Offer амбициозных Java-разработчиков, которые готовы создавать AI‑продукты уровня BigTech и стать частью крупнейшего AI-комьюнити.

Если ты дружишь с Java (версии 8–25), ладишь со Spring и Hibernate, а PostgreSQL и ClickHouse для тебя — не просто слова, переходи по ссылке и занимай слот на One Day Offer.

Встречаемся 23 мая — очень ждём именно тебя!
👍 6
🔥 1
5 1.7K
Небольшой, но полезный совет для Spring Boot.

Если у вас есть scheduled task, не стоит хардкодить интервал прямо в аннотации:


`@Scheduled(fixedRate = 5000)`


Лучше вынести значение в конфиг:


`@Scheduled(fixedRateString = "${task.interval}")`


А в application.properties указать:


`task.interval=5000`


Почему так лучше:

• интервал можно менять без правки кода;
• настройки проще различать для dev, staging и production;
• меньше магических чисел в бизнес-логике;
• конфигурация становится прозрачнее.

Мелочь, но именно из таких мелочей и складывается нормальная поддерживаемость Spring Boot-проекта.
👍 16
2 8 1.6K
emoji CORS в Spring Boot: не лечите это костылями на фронте

Если frontend и backend живут на разных доменах или портах, браузер начнет резать запросы по CORS. Это не баг Spring Boot и не проблема React. Это нормальный механизм безопасности браузера.

Правильный способ - настроить CORS на стороне backend.

В Spring Boot это можно сделать глобально через WebMvcConfigurer: указать маршруты, разрешенные origins, HTTP-методы, заголовки и работу с credentials.

Главное - не ставить бездумно * везде подряд, особенно если используете cookies, токены или allowCredentials(true). В проде лучше явно перечислять доверенные домены, например frontend-домен приложения.

Такой подход дает централизованный контроль: вы один раз задаете политику CORS и не размазываете настройки по каждому контроллеру.

Для Java backend-разработчика это базовая, но важная вещь: CORS должен быть частью архитектуры API, а не случайной правкой перед деплоем.
👍 5
4 33 1.9K
emoji Spring Boot может тормозить сам себя из-за одного неаккуратного @ComponentScan

В Spring Boot не стоит бездумно писать что-то вроде:

@ComponentScan("com.mycompany")

На первый взгляд удобно: фреймворк сам просканирует весь пакет и найдет нужные компоненты. Но проблема в том, что он может просканировать слишком много.

Это увеличивает время classpath scanning, замедляет старт приложения и иногда подтягивает классы, которые вообще не должны были становиться Spring-компонентами.

Лучший вариант - полагаться на дефолтное поведение:


@SpringBootApplication
public class MyApplication { }


По умолчанию Spring Boot сканирует только подпакеты того пакета, где лежит MyApplication.

Если нужно явно ограничить область сканирования, указывай конкретные подпакеты:


@ComponentScan({
"com.mycompany.myapp.product",
"com.mycompany.myapp.order"
})


Главная мысль простая: @ComponentScan должен быть точным. Чем шире границы сканирования, тем больше лишней работы делает приложение на старте.

#SpringBoot #JavaDev #Java #Backend
👍 8
🔥 4
1
13 2.2K
Spring Boot может уронить API из-за одного лишнего поля в JSON

Классика: приходит запрос с дополнительным полем, которого нет в DTO и ты ловишь UnrecognizedPropertyException. Клиент добавил поле, ты не обновил модель - всё падает.

Решение в одну строку:


@JsonIgnoreProperties(ignoreUnknown = true)
public class UserDTO {
private String name;
private int age;
}


Теперь Jackson просто игнорирует лишние поля вместо того, чтобы ломать приложение.

Полезно, когда API живёт долго, клиенты обновляются быстрее бэка, а ломать совместимость нельзя.
👍 5
4
🔥 2
4 12 2.3K
Завтра тестовое собеседование с Java-разработчиком

13 мая(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.

Как это будет:
📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Виктору

Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.

Переходи в нашего бота, чтобы получить ссылку на эфир →
@shortcut_sh_bot

Реклама.
О рекламодателе.
1
👍 1
😁 1
4 2.2K
🔥 Одна аннотация, которая экономит тонны кода в Spring

@RestController - это не просто удобство, а скрытая магия, про которую многие забывают.

Под капотом это комбинация @Controller + @ResponseBody .

То есть тебе не нужно писать @ResponseBody в каждом методе - всё работает автоматически.

• Меньше бойлерплейта
• чище код
• меньше шансов забыть и получить неожиданный результат

Кажется мелочью, но на больших проектах это реально экономит время и нервы

Если до сих пор используешь @Controller + @ResponseBody вручную - пора упрощать
👍 7
3
🔥 3
1 15 2.3K
⚡️ Java лайфхак: не убивай производительность боксингом

Многие даже не замечают, как теряют скорость из-за автoboxing в Stream API.

❌ Плохо (создаются объекты Integer):
Stream<Integer> boxed = Stream.of(1, 2, 3, 4, 5);
int sum = boxed.reduce(0, Integer::sum);

Каждое число → объект → лишняя память + нагрузка на GC

✅ Хорошо (работа с примитивами):
int sum = IntStream.of(1, 2, 3, 4, 5).sum();

Без лишних объектов. Быстрее. Чище.

Запомни:
- IntStream → для int
- LongStream → для long
- DoubleStream → для double

Если работаешь с числами — всегда используй primitive streams.

Это мелочь, которая на больших данных превращается в реальную экономию ресурсов.

Сохрани, чтобы не писать медленный код.
👍 7
1
4 15 2.5K
🚀 Java - regex без боли

Нашли интересную библиотеку - Sift. Она заменяет весь этот ад с регулярками на нормальный fluent API.

Теперь вместо нечитаемых строк вида:
^[0-9a-fA-F]{6}$

Пишешь код, который реально понимаешь:
.char('#')
.then()
.exactly(6)
.hexDigits()

📌 Что это дает:
- Читаемый и понятный код
- Меньше ошибок в regex
- Быстрее разработка и поддержка

По сути — это как “переводчик” с языка регулярных выражений на человеческий Java-код.

Если когда-нибудь ломал голову над regex -это прям must-have.

#Java #JavaDev
🔥 23
👍 6
4
3 52 2.7K
emoji «Git Pro: от первого коммита до уровня senior» — на Stepik
Пятница, 17:58.


Вы пишете git push --force. И понимаете, что были не в той ветке.

Дальше два сценария. Первый: холодный пот, звонок тимлиду, испорченные выходные. Второй: git reflog, две команды, всё на месте, идёте домой.

Разница между этими сценариями - этот курс.
Git изнутри. Rebase без страха. Конфликты по алгоритму. Pull Request, code review, защита веток, CI/CD. Три модели ветвления - выберете свою.

Скидка 58%, 48 часов: https://stepik.org/course/284799/
2
👍 2
🔥 2
11 2.6K
🚀 Java: безопасное сравнение без NullPointerException

Objects.equals(a, b) — простой способ сравнивать значения без риска словить NPE.

Как это работает:

• Если оба значения null → вернёт true
• Если только одно null → вернёт false
• Если оба не null → вызовет a.equals(b)

Вместо:
a.equals(b) → может упасть с NullPointerException

Используй:
Objects.equals(a, b) → всегда безопасно

Мелочь, которая регулярно спасает от багов в проде.

#Java #JavaDev
👍 20
3
🔥 3
18 2.7K
🚀 Spring Boot: почему нельзя делать длинные транзакции

Длинные транзакции - одна из самых частых причин деградации системы, хотя код при этом может выглядеть «нормально».

Что происходит на самом деле:

- транзакция держит lock в базе
- другие запросы начинают ждать
- растёт latency
- падает throughput
- система перестаёт масштабироваться

📉 Итог - узкое место появляется не в коде, а в БД

❌ Плохой подход:
начать транзакцию → делать бизнес-логику → ходить во внешние API → потом commit

Проблема:
ты держишь блокировки всё это время

✅ Правильный подход:
сначала сделать всю тяжёлую работу (API, расчёты)
потом быстро открыть транзакцию → записать → commit

🧠 Простое правило:
транзакция должна быть максимально короткой
только чтение/запись - ничего лишнего

🔥 Большинство оптимизирует запросы
но сильный рост даёт именно контроль времени транзакций
7
🔥 3
👍 2
3 15 2.7K
⚠️ Spring Boot ошибка, которую делают почти все

Большинство просто добавляет:

spring-boot-starter-web
и не думает дальше.

Но вот в чём проблема 👇

Этот стартер тянет за собой:

- встроенный сервер (Tomcat)
- лишние зависимости
- ненужный overhead

👉 даже если тебе нужен только MVC

💡 Правильный подход:

Если тебе нужен только Spring MVC —
используй:

spring-boot-starter-webmvc

Что это даёт:

• 📦 меньше зависимостей
• ⚡ быстрее запуск
• 🧹 чище архитектура
• 💸 меньше ресурсов

🔥 Когда это критично

- микросервисы
- serverless
- high-load системы
- оптимизация старта

🧠 Инсайт

Чем меньше лишнего ты тащишь в проект
→ тем проще его поддерживать

👉 Не ставь "на всякий случай"
Ставь только то, что реально нужно

#springboot #java

⚡️ Полезные ресурсы по Java 🚀 Max

@javatg
👍 12
6
🔥 2
13 18 2.8K
Сегодня тестовое собеседование с Java-разработчиком

Уже сегодня в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.

Как это будет:
📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Виктору

Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.

Переходи в нашего бота, чтобы получить ссылку на эфир →
@shortcut_sh_bot

Реклама.
О рекламодателе.
👍 1
🔥 1
1 2.6K
🚀 Spring Boot: не делай эту ошибку с filters / interceptors

Многие используют фильтры и интерцепторы неправильно 👇

👉 Они должны быть только для cross-cutting задач
(то, что применяется ко ВСЕМ запросам)

Примеры нормального использования:

🟢 Filters:
- CORS
- Encoding

🟢 Interceptors:
- аутентификация / авторизация
- метрики / логирование
- locale
- общие headers

❌ Главная ошибка:

кладут туда бизнес-логику

Например:
- запрос в БД
- проверка подписки
- сложная логика

Почему это плохо:

- выполняется на КАЖДЫЙ запрос
- создаёт лишнюю нагрузку
- ломает архитектуру
- усложняет тестирование

📉 Итог:

interceptor превращается в «мусорный слой»

💡 Как правильно:

- бизнес-логика → в сервисах
- контроллеры → orchestration

⚡️ Полезные ресурсы по Java 🚀 Max

@javatg
4
👍 3
🔥 1
1 18 2.7K
⚡️ Java совет: перестань терять производительность из-за boxing

Когда используешь Stream<Integer>, JVM создаёт объект Integer для каждого значения.

Это лишние аллокации, нагрузка на GC и замедление кода.

Если работаешь с примитивами — используй primitive streams.

❌ Boxing (медленнее)

Stream<Integer> boxed = Stream.of(1, 2, 3, 4, 5);
int sumBoxed = boxed.reduce(0, Integer::sum);


✅ Без boxing (быстрее и эффективнее)


int sumPrimitive = IntStream.of(1, 2, 3, 4, 5).sum();


Другие primitive streams:

IntStream

LongStream

DoubleStream

Когда это критично:

• большие коллекции

• high-load сервисы

• data processing
• performance-sensitive код

Правило простое: Если работаешь с числами - используй primitive streams, а не обёртки.

⚡️ Полезные ресурсы по Java 🚀 Max

@javatg
8
👍 6
🔥 2
3 14 2.6K
⚠️ Маленькая настройка в Spring Boot, которая может спасти от скрытых багов.

Лучше не менять значение по умолчанию:


spring.main.allow-bean-definition-overriding=false


Что это делает?
Если в приложении два бина с одинаковым именем, Spring не запустится.

И это на самом деле хорошо.

Почему:
✔ помогает сразу увидеть конфликт конфигурации
✔ не даёт одному бину тихо перезаписать другой
✔ предотвращает скрытые баги в DI

Если же включить:


spring.main.allow-bean-definition-overriding=true


• тогда второй бин молча перезапишет первый.

В результате приложение запустится, но будет использовать не тот бин, который вы ожидали.

И такие баги потом очень сложно найти.

Иногда лучше получить ошибку при старте, чем искать проблему в продакшене.

#SpringBoot #Java #Backend

⚡️ Полезные ресурсы по Java 🚀 Max

@javatg
👍 8
🔥 4
2
5 16 2.7K