image_2025-08-28_07-49-08.png
3.2 MB
Дорожная карта по Spring Framework
🔸 Prerequisites
• Java Fundamentals. ООП, коллекции, обработка исключений
• Maven и Gradle. Сборка и управление зависимостями
• XML и Annotations. Форматы конфигурации
• Basic SQL.
• JDBC. Драйверы и соединения
• HTTP и Web Basics. REST, JSON, базовые протоколы
🔸 Spring Core
• Inversion of Control. Базовый принцип Spring
• Dependency Injection. Конструктор, сеттер, field injection
• Application Context. Контейнер и управление бинами
• Bean Lifecycle. Инициализация и уничтожение
• Bean Scopes. Singleton, prototype, request, session
• Configuration. XML, Java-config, аннотации
🔸 Core Annotations
•
•
•
•
•
•
•
🔸 Spring Boot Basics
• Auto-Configuration. Автонастройка на зависимостях
• Spring Boot Starters. Преднастроенные наборы
• Application Properties. properties и YAML
• @SpringBootApplication. Точка входа
• Embedded Servers. Tomcat, Jetty, Undertow
• Spring Boot CLI. Инструмент командной строки
🔸 Spring Web MVC
• DispatcherServlet. Фронт-контроллер
•
•
•
•
• Model and View. Шаблоны MVC
🔸 REST APIs
•
•
• HTTP Status Codes.
• Content Negotiation. Форматы JSON и XML
• Exception Handling. @ControllerAdvice и обработчики
• CORS. Политика совместного использования
🔸 Spring Data JPA
• JPA Entities. @Entity, @Table, @Id, аннотации
• Repository Pattern. Интерфейсы доступа к данным
• JpaRepository. CRUD-операции
• Query Methods. Методы-запросы по имени
•
• Relationships. @OneToMany, @ManyToOne, @ManyToMany
• Pagination и Sorting. Параметры страниц и сортировки
🔸 Spring Security
• Authentication. Проверка пользователя
• Authorization. Контроль доступа по ролям
• Security Configuration. Фильтры и цепочка безопасности
• Password Encoding. Энкодеры паролей
• JWT Tokens. Статлес-аутентификация
• OAuth2. Внешние провайдеры
• Method Security. @PreAuthorize, @Secured
🔸 Aspect-Oriented Programming
• Cross-cutting Concerns. Логирование, безопасность, транзакции
•
• Pointcuts. Точки среза
• Advice Types. @Before, @After, @Around
• JoinPoints. Места, куда вплетается аспект
🔸 Testing
•
•
•
• MockMvc. Тесты контроллеров без сервера
•
• TestRestTemplate. Тестирование REST
🔸 Spring Actuator
• Health Endpoints. Мониторинг состояния
• Metrics. Метрики приложения
• Custom Endpoints. Пользовательские эндпоинты
• Info Endpoint. Информация о сборке
• Environment Properties. Просмотр конфигурации
🔸 Microservices
• Spring Cloud. Набор для микросервисов
• Service Discovery. Eureka и Consul
• API Gateway. Spring Cloud Gateway
• Circuit Breaker. Resilience4j и Hystrix
• Configuration Server. Централизованная конфигурация
• Distributed Tracing. Sleuth и Zipkin
🔸 Advanced Topics
• Reactive Programming. Project Reactor
• Spring Native. Компиляция в native-image
• Custom Auto-Configuration. Свои автоконфигурации
• Event-Driven Architecture. Событийная модель
• Caching. Абстракция кэширования
• Profiles. Профили конфигураций
🔸 Deployment
• Docker Containerization. Образы и контейнеры
• Kubernetes Deployment. Манифесты и Helm
• Cloud Platforms. AWS, GCP, Azure
• CI/CD Pipelines. Стратегии релизов
• Production Monitoring. APM и наблюдаемость
🔸 Best Practices
• Project Structure. Слои и модульность
• Configuration Management. Внешние конфиги
• Error Handling. Глобальные обработчики
• Logging. SLF4J и структурированные логи
• Performance Optimization. Кэш, пул соединений, lazy-loading
• Security Hardening. Настройки для продакшена
👉 Java Portal
• Java Fundamentals. ООП, коллекции, обработка исключений
• Maven и Gradle. Сборка и управление зависимостями
• XML и Annotations. Форматы конфигурации
• Basic SQL.
• JDBC. Драйверы и соединения
• HTTP и Web Basics. REST, JSON, базовые протоколы
• Inversion of Control. Базовый принцип Spring
• Dependency Injection. Конструктор, сеттер, field injection
• Application Context. Контейнер и управление бинами
• Bean Lifecycle. Инициализация и уничтожение
• Bean Scopes. Singleton, prototype, request, session
• Configuration. XML, Java-config, аннотации
•
@Component
. Базовый компонент•
@Service
. Слой бизнес-логики•
@Repository
. Доступ к данным•
@Controller
. Обработка запросов•
@Autowired
. Внедрение зависимостей•
@Configuration
. Классы конфигурации•
@Bean
. Определение бина• Auto-Configuration. Автонастройка на зависимостях
• Spring Boot Starters. Преднастроенные наборы
• Application Properties. properties и YAML
• @SpringBootApplication. Точка входа
• Embedded Servers. Tomcat, Jetty, Undertow
• Spring Boot CLI. Инструмент командной строки
• DispatcherServlet. Фронт-контроллер
•
@RequestMapping
. Маршруты•
@GetMapping
и @PostMapping
. HTTP-хендлеры•
@RequestParam
. Параметры запроса•
@PathVariable
. Параметры пути• Model and View. Шаблоны MVC
•
@RestController
. Контроллер REST•
@ResponseBody
. Тело ответа• HTTP Status Codes.
• Content Negotiation. Форматы JSON и XML
• Exception Handling. @ControllerAdvice и обработчики
• CORS. Политика совместного использования
• JPA Entities. @Entity, @Table, @Id, аннотации
• Repository Pattern. Интерфейсы доступа к данным
• JpaRepository. CRUD-операции
• Query Methods. Методы-запросы по имени
•
@Query Annotation
. JPQL и нативные запросы• Relationships. @OneToMany, @ManyToOne, @ManyToMany
• Pagination и Sorting. Параметры страниц и сортировки
• Authentication. Проверка пользователя
• Authorization. Контроль доступа по ролям
• Security Configuration. Фильтры и цепочка безопасности
• Password Encoding. Энкодеры паролей
• JWT Tokens. Статлес-аутентификация
• OAuth2. Внешние провайдеры
• Method Security. @PreAuthorize, @Secured
• Cross-cutting Concerns. Логирование, безопасность, транзакции
•
@Aspect
. Определение аспектов• Pointcuts. Точки среза
• Advice Types. @Before, @After, @Around
• JoinPoints. Места, куда вплетается аспект
•
@SpringBootTest
. Интеграционные тесты•
@WebMvcTest
. Тестирование веб-слоя•
@DataJpaTest
. Тестирование JPA• MockMvc. Тесты контроллеров без сервера
•
@MockBean
. Заглушки в контексте Spring• TestRestTemplate. Тестирование REST
• Health Endpoints. Мониторинг состояния
• Metrics. Метрики приложения
• Custom Endpoints. Пользовательские эндпоинты
• Info Endpoint. Информация о сборке
• Environment Properties. Просмотр конфигурации
• Spring Cloud. Набор для микросервисов
• Service Discovery. Eureka и Consul
• API Gateway. Spring Cloud Gateway
• Circuit Breaker. Resilience4j и Hystrix
• Configuration Server. Централизованная конфигурация
• Distributed Tracing. Sleuth и Zipkin
• Reactive Programming. Project Reactor
• Spring Native. Компиляция в native-image
• Custom Auto-Configuration. Свои автоконфигурации
• Event-Driven Architecture. Событийная модель
• Caching. Абстракция кэширования
• Profiles. Профили конфигураций
• Docker Containerization. Образы и контейнеры
• Kubernetes Deployment. Манифесты и Helm
• Cloud Platforms. AWS, GCP, Azure
• CI/CD Pipelines. Стратегии релизов
• Production Monitoring. APM и наблюдаемость
• Project Structure. Слои и модульность
• Configuration Management. Внешние конфиги
• Error Handling. Глобальные обработчики
• Logging. SLF4J и структурированные логи
• Performance Optimization. Кэш, пул соединений, lazy-loading
• Security Hardening. Настройки для продакшена
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤7
Вот суть работы HashMap:
Сначала вызывается
Внутри бакета вызывается
Если переопределить только equals(), но оставить дефолтный
Итог: поиск по ключу может “ломаться”, значения будут “теряться”, а одинаковые по смыслу ключи могут храниться дублирующимися.
Поэтому существует контракт: если объекты равны по
👉 Вывод прост. Всегда переопределяй
👉 Java Portal
Сначала вызывается
hashCode()
, чтобы определить, в какой бакет попадёт ключ.Внутри бакета вызывается
equals()
, чтобы проверить, есть ли уже такой ключ.Если переопределить только equals(), но оставить дефолтный
hashCode()
(по адресу в памяти), получится проблема. Два объекта, которые равны по equals()
, могут иметь разные хэши. Тогда они попадут в разные бакеты, и HashMap воспримет их как разные ключи.Итог: поиск по ключу может “ломаться”, значения будут “теряться”, а одинаковые по смыслу ключи могут храниться дублирующимися.
Поэтому существует контракт: если объекты равны по
equals()
, они обязаны возвращать одинаковый hashCode()
. В противном случае любые коллекции на основе хэшей (HashMap, HashSet, Hashtable) будут вести себя неправильно.equals()
и hashCode()
вместе.Please open Telegram to view this post
VIEW IN TELEGRAM
👍12👀3
10 принципов проектирования микросервисов, которые стоит изучить Java-разработчикам
- CQRS
- SAGA
- База данных на каждый сервис
- Circuit-breaker
- API Gateway
- Event Sourcing
- Strangler
- Внешняя конфигурация
👉 Java Portal
- CQRS
- SAGA
- База данных на каждый сервис
- Circuit-breaker
- API Gateway
- Event Sourcing
- Strangler
- Внешняя конфигурация
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍2👀2
Вот классический вопрос для собеседования по Java, на котором спотыкается много разработчиков.
Нам всем говорили, что блок
Можешь назвать ситуацию, когда он не сработает?
Ответ — нет, но с важной оговоркой.
Фатальный краш JVM (например, StackOverflowError) это стопроцентный «нет» для finally.
А вот с
То есть поведение реально зависит от прав, заданных в рантайме.
👉 Java Portal
Нам всем говорили, что блок
finally
выполняется всегда, при любых обстоятельствах. Но так ли это на самом деле?Можешь назвать ситуацию, когда он не сработает?
Ответ — нет, но с важной оговоркой.
Фатальный краш JVM (например, StackOverflowError) это стопроцентный «нет» для finally.
А вот с
System.exit()
всё интереснее. Если вызов проходит успешно, JVM завершается сразу, и finally
пропускается. Если же SecurityManager блокирует вызов, выбрасывается SecurityException
, и блок finally
выполняется в рамках обычной обработки ошибки.То есть поведение реально зависит от прав, заданных в рантайме.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤4
Что такое ETL
ETL расшифровывается как Extract, Transform, Load и означает процесс интеграции данных. Сначала данные извлекаются из разных источников, например из баз данных, файлов или API. Затем они преобразуются в удобный для аналитики или отчетности формат.
На этом этапе может выполняться очистка от дублей и ошибок, обогащение за счет других источников, агрегация и сведение, преобразование типов и форматов, применение бизнес-правил или вычислений.
После этого данные загружаются в целевую систему. Чаще всего это хранилище или витрина данных, где они используются для отчетности, BI и аналитики.
ETL применяют в разных задачах. Он лежит в основе построения хранилищ, помогает при миграции данных между системами, используется для интеграции данных из разных источников, обеспечивает корректность данных для BI и отчетов, а также загружает структурированные и неструктурированные данные в data lake.
Среди распространенных ETL-инструментов можно назвать Microsoft SSIS, Azure Data Factory, Talend, Oracle Data Integrator, Apache NiFi и AWS Glue.
Сегодня также популярен подход ELT, при котором данные сначала извлекаются и загружаются в хранилище или big data-платформу, а все трансформации выполняются уже внутри целевой системы.
👉 Java Portal
ETL расшифровывается как Extract, Transform, Load и означает процесс интеграции данных. Сначала данные извлекаются из разных источников, например из баз данных, файлов или API. Затем они преобразуются в удобный для аналитики или отчетности формат.
На этом этапе может выполняться очистка от дублей и ошибок, обогащение за счет других источников, агрегация и сведение, преобразование типов и форматов, применение бизнес-правил или вычислений.
После этого данные загружаются в целевую систему. Чаще всего это хранилище или витрина данных, где они используются для отчетности, BI и аналитики.
ETL применяют в разных задачах. Он лежит в основе построения хранилищ, помогает при миграции данных между системами, используется для интеграции данных из разных источников, обеспечивает корректность данных для BI и отчетов, а также загружает структурированные и неструктурированные данные в data lake.
Среди распространенных ETL-инструментов можно назвать Microsoft SSIS, Azure Data Factory, Talend, Oracle Data Integrator, Apache NiFi и AWS Glue.
Сегодня также популярен подход ELT, при котором данные сначала извлекаются и загружаются в хранилище или big data-платформу, а все трансформации выполняются уже внутри целевой системы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1🔥1🌭1
Как сделать так, чтобы Spring-приложение динамически включало или отключало фичи без изменения Java-кода? Подсказка: условные бины — ключ к решению 👀
Условные бины позволяют управлять созданием и загрузкой бина в Spring по определённому условию. Это как
Для этого используют аннотации, начинающиеся с
Примеры часто используемых аннотаций:
👉 Java Portal
Условные бины позволяют управлять созданием и загрузкой бина в Spring по определённому условию. Это как
if
для компонентов. Так можно сделать приложение гибким -> включать и отключать фичи или менять поведение через конфиг или зависимости проекта, не меняя Java-код.Для этого используют аннотации, начинающиеся с
@Conditional
, которые ставят на методы с @Bean
или на классы с @Component
. Если условие выполнено, Spring создаёт бин. Если нет, то бин игнорируется.Примеры часто используемых аннотаций:
@ConditionalOnProperty
проверяет, есть ли у свойства в application.properties заданное значение. Это основной способ для feature toggling.@ConditionalOnClass
проверяет, есть ли определённый класс в classpath. Удобно, если нужно создавать бин только при наличии библиотеки.@ConditionalOnMissingBean
создаёт бин, только если нет другого бина такого же типа. Подходит для дефолтных или fallback-компонентов.@ConditionalOnWebApplication
создаёт бин только если приложение работает как веб-приложение, например под Tomcat.Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍6
А что если Java-приложение могло бы запускаться за миллисекунды и потреблять совсем немного памяти, как программы на Go или C++
GraalVM решает эту задачу. Он компилирует Java и Spring Boot напрямую в нативный исполняемый файл. Это происходит заранее на этапе сборки в отличие от стандартной JVM, которая компилирует код во время выполнения. В результате получается бинарь, который запускается без JVM
Преимущества заметные, почти мгновенный старт, сокращенное потребление памяти, меньший размер пакета. Такой подход особенно удобен для микросервисов и облачных приложений
Есть и минусы, время сборки увеличивается, а итоговый бинарь зависит от платформы. Для Linux и Windows нужны отдельные файлы в отличие от переносимого JAR
По производительности GraalVM нативные образы близки к C++. Старт сопоставим по скорости. При тяжелых вычислительных задачах преимущество может быть у C++ благодаря управлению памятью на низком уровне. Но для большинства сценариев GraalVM выводит Java в ту же лигу, что и C++, сохраняя при этом безопасность и удобство разработки
👉 Java Portal
GraalVM решает эту задачу. Он компилирует Java и Spring Boot напрямую в нативный исполняемый файл. Это происходит заранее на этапе сборки в отличие от стандартной JVM, которая компилирует код во время выполнения. В результате получается бинарь, который запускается без JVM
Преимущества заметные, почти мгновенный старт, сокращенное потребление памяти, меньший размер пакета. Такой подход особенно удобен для микросервисов и облачных приложений
Есть и минусы, время сборки увеличивается, а итоговый бинарь зависит от платформы. Для Linux и Windows нужны отдельные файлы в отличие от переносимого JAR
По производительности GraalVM нативные образы близки к C++. Старт сопоставим по скорости. При тяжелых вычислительных задачах преимущество может быть у C++ благодаря управлению памятью на низком уровне. Но для большинства сценариев GraalVM выводит Java в ту же лигу, что и C++, сохраняя при этом безопасность и удобство разработки
Please open Telegram to view this post
VIEW IN TELEGRAM
👀8🔥6❤3
Если хочешь уверенно проходить собеседования по системному дизайну, есть набор простых эвристик, которые помогают быстро подобрать решение под типовую задачу. Вот краткий список:
👉 Java Portal
• Задержки + глобальная аудитория → CDN. Доставляем данные с edge-серверов, чтобы уменьшить latency.
• Чтение + узкое место → кэш. Часто читаемые данные кладём в кэш, разгружая базу.
• Запись + всплеск трафика → очередь. Пишем асинхронно, сглаживая пики нагрузки.
• Распределённая транзакция → Saga. Координируем шаги с компенсациями между сервисами.
• ACID + реляционка → SQL. Строгая консистентность и транзакции.
• Гибкость + масштаб → NoSQL. Подходит для схемы без фиксированной структуры и горизонтального масштабирования.
• SQL + рост → шардинг. Делим базу на шарды, чтобы тянуть нагрузку.
• Нагрузка + рост → scale out. Добавляем сервера, а не апгрейдим один.
• Трафик + надёжность → балансировка. Распределяем запросы для стабильности.
• Критичные сервисы + отказ → резервирование. Дублируем, чтобы не было single point of failure.
• Долговечность + сбои → репликация. Держим копии данных для доступности и восстановления.
• Запросы + всплески → троттлинг. Ограничиваем лишние запросы.
• Нагрузка + пики → автоскейлинг. Автоматически подгоняем мощность под трафик.
• Реалтайм + обновления → WebSockets. Двунаправленное живое соединение.
• Повтор + безопасность → идемпотентность. Повторяем операции без побочных эффектов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤯4
Не знаешь, как написать Dockerfile?
Не переживай, Spring Boot сделает это за тебя.😁
Вот как это работает.
В Spring Boot есть встроенный механизм для сборки Docker-образов без Dockerfile. Начиная с версии 2.3, он использует buildpacks, чтобы упаковать твоё приложение вместе с JDK в стандартный OCI-образ. Образ собирается слоями: зависимости, ресурсы и твой код разделяются, что ускоряет пересборку. После этого образ можно запускать как обычный Docker-контейнер.
👉 Java Portal
Не переживай, Spring Boot сделает это за тебя.
Вот как это работает.
В Spring Boot есть встроенный механизм для сборки Docker-образов без Dockerfile. Начиная с версии 2.3, он использует buildpacks, чтобы упаковать твоё приложение вместе с JDK в стандартный OCI-образ. Образ собирается слоями: зависимости, ресурсы и твой код разделяются, что ускоряет пересборку. После этого образ можно запускать как обычный Docker-контейнер.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯15👍3❤2
Spring Boot с одной БД работает гладко. Но как только подключаешь вторую, то всё ломается. Почему и как это правильно настроить?
С одной базой Spring Boot сам автоконфигурит нужные компоненты:
Когда баз становится две, фреймворк не понимает, какую взять за основную. Автоконфигурация перестаёт работать, и нужно явно объявить бины для каждой, одну пометить как✏️
У кого так было?👍
👉 Java Portal
С одной базой Spring Boot сам автоконфигурит нужные компоненты:
DataSource, JdbcTemplate, EntityManagerFactory
и т.д.Когда баз становится две, фреймворк не понимает, какую взять за основную. Автоконфигурация перестаёт работать, и нужно явно объявить бины для каждой, одну пометить как
@Primary
. А дальше подключать их через @Qualifier
там, где требуется. У кого так было?
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍4❤3
Скучаешь? Попробуй собрать что-нибудь своё:
• 3D игру
• 3D-рендерер
• Свой язык для JVM
• свой первый блокчейн на Java
• Android-приложение для Reddit
И это только начало, вот целая подборка✌️
👉 Java Portal
• 3D игру
• 3D-рендерер
• Свой язык для JVM
• свой первый блокчейн на Java
• Android-приложение для Reddit
И это только начало, вот целая подборка
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9
Когда ты создаешь бин в Spring, его scope определяет, сколько времени он будет жить и как именно шариться между разными частями приложения.
По умолчанию все бины работают как singleton. Это значит, что Spring поднимает один экземпляр при старте и потом везде отдает именно его. Такой вариант подходит для сервисов и репозиториев, где не нужно хранить состояние.
Есть вариант prototype. В этом случае при каждом запросе Spring возвращает новый экземпляр. Но если прототип внедрен внутрь singleton, то на деле получится один и тот же объект, потому что сам singleton создается один раз и сохраняет то, что ему подкинули при инициализации.
В веб-приложениях добавляются дополнительные варианты.
Request создает новый бин на каждый HTTP-запрос.
Session закрепляет бин за конкретной пользовательской сессией, так что один и тот же объект сохраняется для одного пользователя между запросами.
Application делает бин общим для всего приложения, по сути работает как singleton, но привязан к контексту сервлета.
Websocket создает бин, живущий столько, сколько длится одно websocket-соединение.
Если свести все в одно короткое объяснение, singleton глобален, prototype всегда создает новый объект, а веб-скоупы зависят от времени жизни запроса или сессии.🍺
👉 Java Portal
По умолчанию все бины работают как singleton. Это значит, что Spring поднимает один экземпляр при старте и потом везде отдает именно его. Такой вариант подходит для сервисов и репозиториев, где не нужно хранить состояние.
Есть вариант prototype. В этом случае при каждом запросе Spring возвращает новый экземпляр. Но если прототип внедрен внутрь singleton, то на деле получится один и тот же объект, потому что сам singleton создается один раз и сохраняет то, что ему подкинули при инициализации.
В веб-приложениях добавляются дополнительные варианты.
Request создает новый бин на каждый HTTP-запрос.
Session закрепляет бин за конкретной пользовательской сессией, так что один и тот же объект сохраняется для одного пользователя между запросами.
Application делает бин общим для всего приложения, по сути работает как singleton, но привязан к контексту сервлета.
Websocket создает бин, живущий столько, сколько длится одно websocket-соединение.
Если свести все в одно короткое объяснение, singleton глобален, prototype всегда создает новый объект, а веб-скоупы зависят от времени жизни запроса или сессии.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍9
Уровни изоляции в базах данных за 5 минут
ACID описывает свойства, гарантирующие надежность транзакций. Но даже если СУБД заявляет поддержку ACID, по умолчанию она может использовать более слабый уровень изоляции.
Разным приложениям нужно разное, где-то важна скорость и можно потерпеть небольшие несостыковки, а где-то критична строгая целостность данных. Проблема в том, что параллельное выполнение транзакций без контроля ведет к аномалиям: dirty read, non-repeatable read, phantom read
Уровни изоляции определяют, насколько одна транзакция защищена от последствий других, выполняющихся одновременно.
• Read Uncommitted (минимальный уровень)
Транзакции вообще не изолированы. Видно изменения других транзакций даже до их коммита. Это может привести к dirty reads.
• Read Committed
Транзакция видит только закоммиченные данные. Dirty reads исключены, но non-repeatable reads остаются возможны.
• Repeatable Read
Транзакция работает с "замороженным снимком" базы на момент старта. Изменения других транзакций ей не видны. Реализация бывает через блокировки (shared locks) или MVCC (мультиверсии строк). Это убирает non-repeatable reads.
• Serializable
Максимальная строгость. Всё выглядит так, будто транзакции идут последовательно одна за другой. Для этого применяются жесткие блокировки вроде range/predicate locks.
Чем выше уровень изоляции, тем больше гарантий целостности, но тем сильнее удар по производительности. Нужно выбирать баланс под конкретную задачу.😣
👉 Java Portal
ACID описывает свойства, гарантирующие надежность транзакций. Но даже если СУБД заявляет поддержку ACID, по умолчанию она может использовать более слабый уровень изоляции.
Разным приложениям нужно разное, где-то важна скорость и можно потерпеть небольшие несостыковки, а где-то критична строгая целостность данных. Проблема в том, что параллельное выполнение транзакций без контроля ведет к аномалиям: dirty read, non-repeatable read, phantom read
Уровни изоляции определяют, насколько одна транзакция защищена от последствий других, выполняющихся одновременно.
• Read Uncommitted (минимальный уровень)
Транзакции вообще не изолированы. Видно изменения других транзакций даже до их коммита. Это может привести к dirty reads.
• Read Committed
Транзакция видит только закоммиченные данные. Dirty reads исключены, но non-repeatable reads остаются возможны.
• Repeatable Read
Транзакция работает с "замороженным снимком" базы на момент старта. Изменения других транзакций ей не видны. Реализация бывает через блокировки (shared locks) или MVCC (мультиверсии строк). Это убирает non-repeatable reads.
• Serializable
Максимальная строгость. Всё выглядит так, будто транзакции идут последовательно одна за другой. Для этого применяются жесткие блокировки вроде range/predicate locks.
Чем выше уровень изоляции, тем больше гарантий целостности, но тем сильнее удар по производительности. Нужно выбирать баланс под конкретную задачу.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥2
Задумывался, почему случайные числа в Java на самом деле не совсем случайные? 😏
В Java они генерируются с помощью так называемого псевдослучайного генератора чисел. Ключевое слово тут «псевдо» - числа выглядят случайными, но на самом деле вычисляются на основе исходного значения - seed (зерна).
Seed задаёт начальное состояние генератора. Если создать два генератора с одинаковым seed, они будут возвращать абсолютно одинаковую последовательность чисел. Это делает случайные числа воспроизводимыми, что удобно для тестов или симуляций.
Если seed явно не указывать, Java использует текущее системное время для инициализации. Поэтому при каждом запуске результат будет разным.
👉 Java Portal
В Java они генерируются с помощью так называемого псевдослучайного генератора чисел. Ключевое слово тут «псевдо» - числа выглядят случайными, но на самом деле вычисляются на основе исходного значения - seed (зерна).
Seed задаёт начальное состояние генератора. Если создать два генератора с одинаковым seed, они будут возвращать абсолютно одинаковую последовательность чисел. Это делает случайные числа воспроизводимыми, что удобно для тестов или симуляций.
Если seed явно не указывать, Java использует текущее системное время для инициализации. Поэтому при каждом запуске результат будет разным.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥2
JEP 519: Compact Object Headers готов к релизу вместе с Java25
А ещё подъехали Compact Source Files
👉 Java Portal
А ещё подъехали Compact Source Files
Please open Telegram to view this post
VIEW IN TELEGRAM
😁14❤7
В работе с API на Spring Boot часто встречаются три термина: DTO, ModelMapper, Jackson. Разберём, что это и зачем нужно.
1. DTO
DTO это простой Java-класс, который используется для передачи данных между слоями (Controller <-> Service <-> Client).
Почему не использовать Entity напрямую?
- В Entity часто есть лишние поля (ID из БД, служебные поля аудита), которые клиенту видеть не нужно.
- Можно случайно засветить чувствительные данные.
- DTO позволяет держать API-контракты стабильными, даже если структура базы поменялась.
Пример DTO:
2. ModelMapper
ModelMapper это библиотека для автоматического маппинга DTO <-> Entity.
Без него пришлось бы вручную писать:
С ModelMapper это превращается в:
Плюсы: меньше шаблонного кода.
Минусы: для сложных кейсов нужна настройка, а ещё можно легко пропустить баг в маппинге, если полагаться только на автоматику.
3. Jackson
Jackson это библиотека, которую Spring Boot использует для (де)сериализации JSON.
Что делает:
- Превращает Java-объекты в JSON (ответ API).
- Превращает JSON в Java-объекты (тело запроса).
Пример:
автоматически маппится в UserDTO в контроллере.
Как они работают вместе:
- Jackson: JSON <-> DTO
- ModelMapper: DTO <-> Entity
- DTO: слой-контракт между внешними клиентами и внутренними моделями
DTO защищает доменную модель, Jackson работает с JSON, а ModelMapper убирает рутину маппинга.
👉 Java Portal
1. DTO
DTO это простой Java-класс, который используется для передачи данных между слоями (Controller <-> Service <-> Client).
Почему не использовать Entity напрямую?
- В Entity часто есть лишние поля (ID из БД, служебные поля аудита), которые клиенту видеть не нужно.
- Можно случайно засветить чувствительные данные.
- DTO позволяет держать API-контракты стабильными, даже если структура базы поменялась.
Пример DTO:
class UserDTO {
private String name;
private String email;
}
2. ModelMapper
ModelMapper это библиотека для автоматического маппинга DTO <-> Entity.
Без него пришлось бы вручную писать:
dto.setName(entity.getName());
dto.setEmail(entity.getEmail());
С ModelMapper это превращается в:
UserDTO dto = modelMapper.map(userEntity, UserDTO.class);
Плюсы: меньше шаблонного кода.
Минусы: для сложных кейсов нужна настройка, а ещё можно легко пропустить баг в маппинге, если полагаться только на автоматику.
3. Jackson
Jackson это библиотека, которую Spring Boot использует для (де)сериализации JSON.
Что делает:
- Превращает Java-объекты в JSON (ответ API).
- Превращает JSON в Java-объекты (тело запроса).
Пример:
{ "name": "Sumit", "email": "sumit@email.com" }
автоматически маппится в UserDTO в контроллере.
Как они работают вместе:
- Jackson: JSON <-> DTO
- ModelMapper: DTO <-> Entity
- DTO: слой-контракт между внешними клиентами и внутренними моделями
DTO защищает доменную модель, Jackson работает с JSON, а ModelMapper убирает рутину маппинга.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍7
Ты на собеседовании на бэкенд-разработчика. Интервьюер спрашивает:
В чем разница между
Обычно на это отвечают размыто. Давай разложим по полочкам.
Что такое Future
• Появился в Java 5 вместе с Executor framework.
• Представляет результат асинхронного вычисления.
• Обычно ты отдаешь
С ним можно:
• вызвать
• вызвать
• вызвать
И на этом все.
Что добавляет CompletableFuture
• Появился в Java 8, реализует
• Все еще является
• Поддерживает неблокирующие коллбеки (
• Позволяет комбинировать задачи (
• Умеет завершаться вручную через
• Даёт более гибкую обработку ошибок (
Главная разница
С
👉 Java Portal
В чем разница между
Future
и CompletableFuture
в Java?Обычно на это отвечают размыто. Давай разложим по полочкам.
Что такое Future
• Появился в Java 5 вместе с Executor framework.
• Представляет результат асинхронного вычисления.
• Обычно ты отдаешь
Callable
в ExecutorService
, который возвращает Future<T>
.С ним можно:
• вызвать
get()
→ блокирует поток, пока задача не завершится• вызвать
isDone()
→ проверить, закончилась ли задача• вызвать
cancel()
→ попытаться отменить выполнениеИ на этом все.
Future
дает контроль над ожиданием, но никак не управляет тем, что делать, когда результат готов.Что добавляет CompletableFuture
• Появился в Java 8, реализует
Future
и CompletionStage
.• Все еще является
Future
(можно блокироваться, если хочется), но гораздо функциональнее.• Поддерживает неблокирующие коллбеки (
thenApply, thenAccept, thenRun
).• Позволяет комбинировать задачи (
thenCombine, allOf, anyOf
).• Умеет завершаться вручную через
complete()
, чего у Future
нет.• Даёт более гибкую обработку ошибок (
exceptionally, handle
).Главная разница
С
Future
ты просто ждешь результат. С CompletableFuture
ты описываешь, что должно произойти, когда результат появится.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤4
This media is not supported in your browser
VIEW IN TELEGRAM
Полезная находка для разработчиков и студентов - - Wokwi, онлайн-симулятор Arduino и других микроконтроллеров.
Платформа позволяет собирать и запускать проекты прямо в браузере с использованием виртуальных компонентов и встроенных инструментов отладки. Поддерживаются Arduino, ESP32, STM32 и Raspberry Pi Pico.
Wokwi уже набирает популярность в сообществе, так что можно протестировать идеи без физического железа💪
Попробовать можно тут: wokwi.com
👉 Java Portal
Платформа позволяет собирать и запускать проекты прямо в браузере с использованием виртуальных компонентов и встроенных инструментов отладки. Поддерживаются Arduino, ESP32, STM32 и Raspberry Pi Pico.
Wokwi уже набирает популярность в сообществе, так что можно протестировать идеи без физического железа
Попробовать можно тут: wokwi.com
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4👀2
Аннотация
Это не баг, а классическая особенность Spring AOP по дизайну.
Знаешь, почему транзакция вообще не стартует?
Проблема в том, как Spring AOP создаёт прокси. Когда ты ставишь
Этот прокси перехватывает внешние вызовы метода, запускает транзакцию и потом делегирует вызов реальному методу бина.
Это отлично работает, когда внешний бин вызывает твой публичный транзакционный метод, потому что вызов проходит через прокси.
Но при самовызове внутри класса (например,
Чтобы исправить, самое чистое и продакшен-готовое решение это вынести транзакционный метод в отдельный Spring-бин и инжектить его. Тогда вызов всегда будет внешним и пройдёт через прокси, корректно поднимая транзакцию каждый раз.🙈
👉 Java Portal
@Transactional
не работает, когда ты вызываешь метод из другого метода в том же классе?Это не баг, а классическая особенность Spring AOP по дизайну.
Знаешь, почему транзакция вообще не стартует?
Проблема в том, как Spring AOP создаёт прокси. Когда ты ставишь
@Transactional
на метод, Spring не правит байткод класса. Вместо этого он создаёт прокси-объект, который оборачивает твой бин.Этот прокси перехватывает внешние вызовы метода, запускает транзакцию и потом делегирует вызов реальному методу бина.
Это отлично работает, когда внешний бин вызывает твой публичный транзакционный метод, потому что вызов проходит через прокси.
Но при самовызове внутри класса (например,
this.someTransactionalMethod()
) ты вызываешь метод напрямую на целевом объекте (this
), а не через прокси. Транзакционный advice прокси полностью обходится, поэтому транзакция не стартует. Это фундаментальное следствие прокси-based AOP.Чтобы исправить, самое чистое и продакшен-готовое решение это вынести транзакционный метод в отдельный Spring-бин и инжектить его. Тогда вызов всегда будет внешним и пройдёт через прокси, корректно поднимая транзакцию каждый раз.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3
Stateful vs Stateless дизайн
Stateless-дизайн сделал возможным простые, но при этом масштабируемые и быстрые приложения. Вместо хранения состояния в памяти сервера, каждый запрос несет все данные для своей обработки. Это убрало лишние накладные расходы и позволило легко масштабировать системы.
Stateful-приложения работают иначе. Они хранят данные вроде user ID, сессий и настроек, что дает персонализацию и избавляет от передачи повторяющейся информации. Но из-за этого тяжело масштабироваться горизонтально.
Stateless-подход стал основой для микросервисов, serverless и REST API. Он ускоряет работу CDN и повышает эффективность сервисов. Но у него есть минусы - - большие размеры запросов, избыточная передача данных и сложности в сценариях, где состояние критично.
На практике чаще выбирают гибрид — сочетание stateful и stateless. Баланс позволяет сделать систему масштабируемой, простой и быстрой, не жертвуя функциональностью💪
👉 Java Portal
Stateless-дизайн сделал возможным простые, но при этом масштабируемые и быстрые приложения. Вместо хранения состояния в памяти сервера, каждый запрос несет все данные для своей обработки. Это убрало лишние накладные расходы и позволило легко масштабировать системы.
Stateful-приложения работают иначе. Они хранят данные вроде user ID, сессий и настроек, что дает персонализацию и избавляет от передачи повторяющейся информации. Но из-за этого тяжело масштабироваться горизонтально.
Stateless-подход стал основой для микросервисов, serverless и REST API. Он ускоряет работу CDN и повышает эффективность сервисов. Но у него есть минусы - - большие размеры запросов, избыточная передача данных и сложности в сценариях, где состояние критично.
На практике чаще выбирают гибрид — сочетание stateful и stateless. Баланс позволяет сделать систему масштабируемой, простой и быстрой, не жертвуя функциональностью
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍3