Java Portal | Программирование
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика Связь: @devmangx РКН: https://clck.ru/3H4WUg
Показати більше📈 Аналітичний огляд Telegram-каналу Java Portal | Программирование
Канал Java Portal | Программирование (@java_iibrary) у мовному сегменті Російська є активним учасником. На даний момент спільнота об'єднує 12 127 підписників, посідаючи 10 404 місце в категорії Технології та додатки та 54 512 місце у регіоні Росія.
📊 Показники аудиторії та динаміка
З моменту свого створення невідомо, проект продемонстрував стрімке зростання, зібравши аудиторію у 12 127 підписників.
За останніми даними від 07 червня, 2026, канал демонструє стабільну активність. Хоча за останні 30 днів спостерігається зміна кількості учасників на -138, а за останні 24 години на 2, загальне охоплення залишається високим.
- Статус верифікації: Не верифікований
- Рівень залученості (ER): Середній показник залученості аудиторії становить 11.37%. Протягом перших 24 годин після публікації контент зазвичай збирає 6.26% реакцій від загальної кількості підписників.
- Охоплення публікацій: В середньому кожен допис отримує 1 379 переглядів. Протягом першої доби публікація в середньому набирає 760 переглядів.
- Реакції та взаємодія: Аудиторія активно підтримує контент: середня кількість реакцій на один пост – 4.
- Тематичні інтереси: Контент зосереджений навколо ключових тем, таких як boot, string, void, архитектура, resttemplate.
📝 Опис та контентна політика
Автор описує ресурс як майданчик для висловлення суб'єктивної думки:
“Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика
Связь: @devmangx
РКН: https://clck.ru/3H4WUg”
Завдяки високій частоті оновлень (останні дані отримано 08 червня, 2026), канал підтримує актуальність та високий рівень охоплення публікацій. Аналітика показує, що аудиторія активно взаємодіє з контентом, що робить його важливою точкою впливу в категорії Технології та додатки.
🎙 Серия 1. Функциональные и нефункциональные требования. Как сбор требований помогает создавать надёжные и масштабируемые решения 🎙 Серия 2. Надёжный API. Принципы проектирования API, которые помогут сделать его консистентным, предсказуемым и поддерживаемым 🎙 Серия 3. Крупноблочная архитектура: карта вашей системы. Как выглядит модель на примере Яндекс Календаря и как ребята применяют её для эффективной коммуникации с различными командами разработки 🎙Серия 4. Практика: Рост баз данных: от единиц запросов к тысячам. Как правильно организовать работу с БД, чтобы система оставалась стабильной и эффективной 🎙 Серия 5. Практика. Взаимодействие со смежными системами. Типичные сложности, с которыми сталкиваются команды при интеграции с внешними сервисами, и как их предотвратить или минимизироватьСмотрите проект, чтобы узнать, как создаются одни из крупнейших облачных сервисов в России: ⭐️ Наш сайт ⭐️ VK Видео ⭐️ Ютуб
@Transactional.
Этот метод не только сохраняет сущность, но и отправляет два письма: одно администратору, другое — пользователю, который сделал запрос.
Класс, отвечающий за отправку почты, помечен аннотацией @Async, но Spring всё равно выполняет его синхронно.
В итоге API обрабатывает запрос целых 12 секунд — очевидно, это неприемлемо.
Вопрос: почему так происходит и как это исправить?
Реальная причина:
Когда используется @Transactional, Spring создаёт прокси для транзакции.
Если внутри этого же контекста вызывается @Async-метод, то Spring не создаёт новый поток — потому что вызов происходит внутри того же прокси.
Иными словами, асинхронный код оказывается «заперт» внутри транзакции.
В результате, коммит в базу ждёт, пока оба письма не будут отправлены.
Как исправить:
Заменить прямой вызов отправки писем на event-publisher подход.
После сохранения запроса просто опубликовать событие, например DemoRequestCreatedEvent.
Асинхронные слушатели (@EventListener + @Async) будут обрабатывать отправку писем вне основной транзакции.
Что получаем:
Транзакция завершается за ~100 мс вместо 12 секунд.
API реагирует почти мгновенно.
Письма всё так же надёжно уходят в фоне.
Использование событий и асинхронных слушателей — не просто красивая архитектурная штука, а реальный способ сделать систему быстрой, масштабируемой и профессиональной.
Дополнительный вопрос:
Кроме событий, какие подходы ты используешь, чтобы отделить транзакционную логику (например, коммит в БД) от побочных эффектов вроде отправки писем или уведомлений?
@Java_IibraryString s1 = "Java";
String s2 = "Java";
System.out.println(s1 == s2); // true
s1 и s2 указывают на один и тот же объект в String Pool → дубликаты не создаются.
Но если сделать так:
String s3 = new String("Java");
System.out.println(s1 == s3); // false
new String() обходит пул и создаёт новый объект в heap.
Зачем это нужно:
→ Экономит память за счёт переиспользования неизменяемых строк.
→ Повышает производительность при повторных строковых значениях.
→ Безопасно для потоков, потому что строки immutable.
Как заставить строку из heap использовать пул?
Ответ:
s3 = s3.intern();
Метод intern() → добавляет строку в пул и возвращает ссылку на объект из пула.
👉 Java Portal@Repository, а где — с аннотацией @Service? Приведи конкретный пример, какую роль каждая из этих аннотаций играет в процессе оформления заказа пользователем.
→
@Component — универсальный бин,
@Service — бизнес-логика,
@Repository — DAO + перевод исключений в DataAccessException,
@Controller — контроллер уровня MVC.
🔸Циклические зависимости
Сценарий: Коллега добавил новую фичу, и теперь твое Spring-приложение не стартует, выдавая BeanCurrentlyInCreationException из-за циклической зависимости между ServiceA и ServiceB.
Предположим, что быстро переработать бизнес-логику невозможно. Какое минимальное изменение кода ты бы предложил, чтобы приложение хотя бы запустилось, и почему это считается временным решением?
→
Spring по умолчанию может использовать проксирование и конструкторную/сеттерную инъекцию.
Лучшее решение — перепроектировать зависимости или использовать @Lazy.
🔸Распространение транзакций
Сценарий: У тебя есть OrderService с методом createOrder(), помеченным @Transactional.
Внутри он вызывает updateInventory() (тоже в OrderService и тоже с @Transactional).
Если updateInventory() выбрасывает runtime-исключение, что произойдет с транзакцией, начатой в createOrder()?
Как изменить дизайн, если нужно, чтобы оба метода выполнялись в отдельных, независимых транзакциях?
→
Транзакция не будет распространяться (прокси не сработает при внутреннем вызове).
Решение — self-injection (внедрение самого себя как зависимости) или использование AOP.
🔸Скоупы бинов
Сценарий: Нужно хранить товары пользователя в корзине и управлять временным списком поисковых фильтров, который очищается после каждого HTTP-запроса.
Какой скоуп ты выберешь для ShoppingCart и какой — для SearchFilter, и почему?
→
@SessionScope — для корзины (привязано к пользовательской сессии),
@RequestScope — для поискового фильтра (новый бин на каждый HTTP-запрос).
🔸Controller Advice
Сценарий: В приложении есть и традиционные веб-эндпоинты с Thymeleaf, и REST API.
Нужно централизовать обработку ошибок (например, перехват ResourceNotFoundException):
Как вернуть страницу 404 для обычных web-эндпоинтов?
Как вернуть JSON с ошибкой 404 для REST API?
→
@ControllerAdvice — используется с @Controller, возвращает view.
@RestControllerAdvice — сочетает @ControllerAdvice + @ResponseBody (для REST API).
🔸Автоконфигурация
Сценарий: Ты добавил в проект стороннюю библиотеку (например, кастомный логгер) и просто положил её JAR в classpath.
Без написания конфигурационных классов Spring автоматически подхватывает нужные бины.
Объясни, как Spring Boot определяет и подключает их при старте.
→
Использует SpringFactoriesLoader, который читает META-INF/spring.factories и конфигурирует бины в зависимости от содержимого classpath.
🔸Ограничение частоты запросов
Сценарий: Твой публичный API перегружен — один клиент шлет слишком много запросов, мешая остальным.
Какой практичный, независимый от технологий подход можно применить для ограничения, например, 100 запросов в минуту на клиента, и где обычно реализуется такая логика?
→
Bucket4j / Resilience4j, счетчики в Redis, лимитирование на уровне API Gateway.
🔸Распределённые транзакции
Сценарий: В микросервисной архитектуре оформление заказа включает два шага — списание товара в Inventory Service и списание денег через Payment Service.
Если списание товара прошло успешно, а оплата — нет, какой шаблон проектирования поможет откатить изменения в Inventory и обеспечить согласованность данных?
→
Шаблон Saga (хореография или оркестрация), либо двухфазный коммит (2PC, но редко используется на практике).
👉 Java Portal@GetMapping, @PostMapping, @PutMapping, @DeleteMapping
- Path variables и request parameters
- Настройка баз данных (H2, MySQL, PostgreSQL)
- Использование JpaRepository и CrudRepository
- Spring Boot DevTools и hot reloading
- Spring Batch, Scheduling и Cron выражения
PHASE 2
- @ControllerAdvice и @ExceptionHandler
- Кастомные ошибки и глобальная обработка исключений
- Базовая аутентификация и настройка безопасности API
- JWT для stateless аутентификации
- HATEOAS и версионирование REST API (URI, параметры, headers)
- Unit-тесты с JUnit и Mockito
- Интеграционные тесты с Spring Boot Test и MockMvc
- Actuator endpoints и кастомные health indicators
PHASE 3
- @Profile и настройка бинов для разных окружений
- Spring Cloud: Eureka Server, Service Discovery, API Gateway
- Spring Cloud Config Server для централизованного управления конфигурациями
- Настройка Spring Boot приложений для работы с Config Server
Чтобы полностью усвоить материал, постройте свои проекты на каждом этапе. Практика поможет закрепить знания и сделает их долговечными.
👉 Java Portal1. Круговой Алгоритм Клиентские запросы отправляются в различные экземпляры сервисов в последовательном порядке. Сервисы обычно должны быть без сохранения состояния. Недостаток: - Эта простейшая версия алгоритма будет эффективно работать только в сферической среде в вакууме, где все серверы обладают почти одинаковой конфигурацией, а все входящие запросы (задачи, процессы) имеют одинаковые приоритет и продолжительность. 2. Закреплённый Круговой Алгоритм Усовершенствование кругового алгоритма. Если первый запрос Алисы отправляется в сервис A, следующие запросы также отправляются в сервис A. 3. Взвешенный Круговой Алгоритм Администратор может указать вес для каждого сервиса. Сервисы с более высоким весом обрабатывают больше запросов, чем другие. 4. Хэш IP/URL Применяет хеш-функцию к IP или URL входящих запросов. Запросы направляются в соответствующие экземпляры на основе результата хеш-функции. Преимущества: - Постоянство сессии – алгоритм гарантирует, что запросы от одного клиента всегда попадают на один и тот же сервер. - Облегчает кеширование данных на стороне сервера для конкретных клиентов. Недостатки: - Если много пользователей приходят из одного диапазона IP, один сервер может быть перегружен. - Неэффективен в средах, где IP клиентов часто меняются (мобильные сети). - Может привести к неравномерной нагрузке, если некоторые клиенты генерируют больше трафика.Динамические алгоритмы
5. Наименьшее Количество Соединений Новый запрос отправляется в экземпляр сервиса с наименьшим количеством одновременных подключений. Преимущества: - Более мощные серверы естественным образом будут обрабатывать больше запросов и, следовательно, иметь больше соединений. И напротив, менее мощные серверы будут получать меньше запросов, что предотвращает их перегрузку. - Гибкость – если один сервер начинает работать медленнее, он будет получать меньше новых запросов. Недостатки: - Алгоритм считает все соединения одинаковыми, не учитывая, что некоторые запросы могут быть более ресурсоёмкими. - Вновь добавленный сервер может получить слишком много запросов, т.к. изначально у него 0 соединений. 6. Наименьшее Время Ответа Новый запрос отправляется в экземпляр сервиса с самым быстрым временем ответа. Аналогичный алгоритм - Наименьший объем трафика Преимущества: - Учёт текущей производительности серверов и динамическая адаптация обеспечивают оптимальный баланс и наилучший пользовательский опыт. - Хорошо работает с серверами разной мощности и приложениями с разными характеристиками. Недостаток: - Сложность реализации – требует постоянного мониторинга и анализа производительности серверов, отсюда повышенная нагрузка на балансировщик.👉 Java Portal
@Query("SELECT a FROM Author a JOIN FETCH a.books")
List<Author> findAllWithBooks();
Плюсы: один эффективный запрос.
Важно: при джойне нескольких коллекций можно получить декартово произведение.
2. Batch Fetching
(@BatchSize или hibernate.default_batch_fetch_size)
Вместо одного запроса на каждого родителя, связанные коллекции загружаются пакетами — по нескольким ID за один запрос.
Пример:
@BatchSize(size = 10)
@OneToMany(...)
private List<Book> books;
Плюсы: уменьшает количество запросов с 1 + N до 1 + (N / batch_size), избегая проблемы декартовых произведений.
3. Entity Graphs
(@EntityGraph — Spring Data JPA / JPA 2.1+)
Позволяет декларативно определить, какие связи нужно подгружать eagerly для конкретного метода репозитория.
Пример:
@EntityGraph(attributePaths = "books")
List<Author> findAll();
Плюсы: гибкая и переиспользуемая стратегия загрузки без явных JPQL JOIN’ов.
Всегда используйте явные стратегии загрузки (такие как JOIN FETCH, @BatchSize или @EntityGraph), чтобы избежать проблемы N+1 и обеспечить эффективное взаимодействие с базой данных.
👉 Java Portal
@Test
void findAll() {
// given
// Все компактно, содержит только необходимую информацию для программиста
User user1 = userDao.save(getUser("test1@gmail.com"));
User user2 = userDao.save(getUser("test2@gmail.com"));
User user3 = userDao.save(getUser("test3@gmail.com"));
// when
List<User> actualResult = userDao.findAll();
// then
// Легко получить доступ к id объектов, т.к. накатывание данных было в самом тесте
assertThat(actualResult).hasSize(3);
List<Integer> userIds = actualResult.stream()
.map(User::getId)
.toList();
assertThat(userIds).contains(user1.getId(), user2.getId(), user3.getId());
}
А чтобы не испортить состояние базы во время проверки, то:
- открываем транзакцию ПЕРЕД выполнением теста (@BeforeEach)
- накатываем данные, вызываем API и проверяем результат (@Test)
- откатываем транзакцию в конце (@AfterEach)
👉 Java Portal@ResponseStatus: простой статический вариант
- Можно навесить на исключение или метод контроллера.
- Всегда возвращает один и тот же HTTP-статус.
- Подход "fire-and-forget": быстро и лаконично в случаях, когда ответ всегда одинаковый.
- Лучше всего подходит для простой обработки ошибок. Например, ResourceNotFoundException, аннотированный @ResponseStatus(HttpStatus.NOT_FOUND), всегда будет возвращать 404.
- Нельзя добавить кастомные заголовки или динамическое тело ответа.
→ ResponseEntity: кастомный инструмент
- Даёт полный программный контроль над формированием HTTP-ответа во время выполнения.
- Можно выставить статус, добавить заголовки и собрать тело ответа так, как требуется по логике.
- Лучше всего подходит для сложных ответов. Например, когда нужно добавить заголовок Location после создания ресурса (201 Created) или вернуть детализированный JSON-объект с информацией об ошибке.
- Это основной инструмент, когда ответ должен зависеть от ситуации.
Комбинация подходов:
Используя @RestControllerAdvice для глобальной обработки исключений, можно применять @ResponseStatus для типовых ошибок, а ResponseEntity — для более специфичных и динамичных ответов. Такой подход даёт одновременно и эффективность, и гибкость.
👉 Java Portal
Вже доступно! Дослідження Telegram за 2025 — головні інсайти року 
