🐳 Java Testing: Хватит мокать базы данных!
Вы всё еще используете H2 для тестов, а в продакшене стоит PostgreSQL? Или, может быть, вы поднимаете
⛔ Как было раньше
Раньше нам приходилось делать трюки с
✅ Как сейчас
Писать контейнер в каждом тестовом классе - дурной тон (и медленно, так как Docker будет стартовать каждый раз заново).
В Spring Boot 3.1 появился паттерн TestConfiguration, который позволяет переиспользовать контейнеры.
Создаем один файл конфигурации:
Теперь в любом тесте просто импортируем этот конфиг:
Вы можете использовать этот же конфиг, чтобы запустить само приложение локально с поднятыми контейнерами! Больше не нужно настраивать локальный Postgres.
В папке
Запускаете
🏁 Итог
• Изоляция: Каждый прогон тестов - чистая среда.
• Честность: Тестируйте на том, что будет в продакшене.
• Удобство:
#SpringTest #Testcontainers #Java #DevOps #Docker
👉 @java_geek
Вы всё еще используете H2 для тестов, а в продакшене стоит PostgreSQL? Или, может быть, вы поднимаете
docker-compose руками перед запуском mvn test?⛔ Как было раньше
Раньше нам приходилось делать трюки с
@DynamicPropertySource, чтобы вручную прокинуть jdbc:url, username и password из поднятого контейнера в контекст Spring.
// Old School (Java 17 / Boot 2.7)
@DynamicPropertySource
static void registerPgProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
// ... куча ручного кода
}
✅ Как сейчас
@ServiceConnection сама понимает, что это за контейнер (Postgres, Redis, Kafka, RabbitMQ), и автоматически прописывает нужные свойства в ваш application.properties на время теста.
@Testcontainers
@SpringBootTest
class OrderIntegrationTest {
// 1. Объявляем контейнер
@Container
@ServiceConnection // 👈 Вся магия тут!
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16-alpine");
@Autowired
private OrderRepository repository;
@Test
void shouldSaveOrder() {
// 2. Тест работает с РЕАЛЬНОЙ базой в Docker
var order = new Order("item-123", BigDecimal.TEN);
repository.save(order);
assertThat(repository.findAll()).hasSize(1);
}
}
Писать контейнер в каждом тестовом классе - дурной тон (и медленно, так как Docker будет стартовать каждый раз заново).
В Spring Boot 3.1 появился паттерн TestConfiguration, который позволяет переиспользовать контейнеры.
Создаем один файл конфигурации:
@TestConfiguration(proxyBeanMethods = false)
public class ContainersConfig {
@Bean
@ServiceConnection
public PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:16-alpine");
}
@Bean
@ServiceConnection
public KafkaContainer kafkaContainer() {
return new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.4.0"));
}
}
Теперь в любом тесте просто импортируем этот конфиг:
@Import(ContainersConfig.class)
@SpringBootTest
class AnyIntegrationTest { ... }
Вы можете использовать этот же конфиг, чтобы запустить само приложение локально с поднятыми контейнерами! Больше не нужно настраивать локальный Postgres.
В папке
src/test/java создайте класс для запуска:
public class TestApplication {
public static void main(String[] args) {
SpringApplication.from(MyRealApplication::main)
.with(ContainersConfig.class) // Подключаем наши контейнеры
.run(args);
}
}
Запускаете
TestApplication -> Spring сам поднимает Docker-контейнеры -> приложение коннектится к ним -> вы работаете.🏁 Итог
• Изоляция: Каждый прогон тестов - чистая среда.
• Честность: Тестируйте на том, что будет в продакшене.
• Удобство:
@ServiceConnection убрал весь бойлерплейт.#SpringTest #Testcontainers #Java #DevOps #Docker
👉 @java_geek
❤5👍3
🚀 Java на стероидах: Запуск за 0.05 сек с GraalVM Native Image
Главный аргумент хейтеров Java: "Она жирная и медленная на старте".
И они правы. JVM нужно время, чтобы прогреться, загрузить классы и скомпилировать байт-код (JIT). Для микросервисов в Kubernetes или Serverless (AWS Lambda) это критично.
Но GraalVM Native Image превращает ваше Java-приложение в нативный бинарник. Без JVM. Без
🏎 JIT vs AOT: В чем разница?
1. Standard JVM (JIT - Just In Time):
Вы запускаете код -> JVM интерпретирует его -> находит "горячие участки" -> компилирует их в машинный код прямо во время работы.
• Плюс: Максимальная производительность на длинной дистанции (Runtime Optimization).
• Минус: Медленный старт, жрет память на компилятор.
2. Native Image (AOT - Ahead Of Time):
Вы компилируете код заранее. Весь "мертвый" код выкидывается. Остается только то, что реально используется.
• Плюс: Мгновенный старт (< 100ms), мизерное потребление памяти.
• Минус: Долгая сборка (build time), нет оптимизаций во время выполнения.
🛠 Как это выглядит на практике?
В Spring Boot 3 поддержка Native Image встроена официально.
1. Добавляем плагин (Gradle):
2. Собираем:
Внимание: Идите пить кофе. Сборка займет от 2 до 10 минут. GraalVM проводит статический анализ всего вашего кода и всех библиотек.
3. Запускаем:
Да, вы не ослышались. Spring Boot поднимается за 50 миллисекунд.
⚠️ Подводные камни (The Pain Points)
Не всё так радужно. Native Image ненавидит динамику.
1. Reflection API: GraalVM должен знать обо всех классах, которые вы загружаете через рефлексию, на этапе сборки. Раньше нужно было писать тонны JSON-конфигов. Сейчас Spring Boot делает это за вас, но сторонние либы могут сломаться.
2. Resources: Если вы читаете файл из
3. Нет "Write Once, Run Anywhere": Бинарник под Linux не запустится на Windows. Сборку нужно делать в той же OS (или в Docker-контейнере), где будет работать код.
📊 Когда использовать?
✅ Serverless (AWS Lambda, Google Cloud Run): Холодный старт больше не проблема.
✅ CLI утилиты: Консольные тулзы на Java теперь работают мгновенно.
✅ Kubernetes (Scale to Zero): Поды поднимаются и умирают за секунды, экономя ресурсы.
⛔ Обычные микросервисы (High Load): Если сервис живет месяцами и молотит тысячи запросов в секунду, обычная JVM (JIT) обгонит Native Image по пропускной способности (Throughput) за счет рантайм-оптимизаций.
#GraalVM #NativeImage #JavaPerformance #SpringBoot3 #Serverless
👉 @java_geek
Главный аргумент хейтеров Java: "Она жирная и медленная на старте".
И они правы. JVM нужно время, чтобы прогреться, загрузить классы и скомпилировать байт-код (JIT). Для микросервисов в Kubernetes или Serverless (AWS Lambda) это критично.
Но GraalVM Native Image превращает ваше Java-приложение в нативный бинарник. Без JVM. Без
java -jar. Просто исполняемый файл.🏎 JIT vs AOT: В чем разница?
1. Standard JVM (JIT - Just In Time):
Вы запускаете код -> JVM интерпретирует его -> находит "горячие участки" -> компилирует их в машинный код прямо во время работы.
• Плюс: Максимальная производительность на длинной дистанции (Runtime Optimization).
• Минус: Медленный старт, жрет память на компилятор.
2. Native Image (AOT - Ahead Of Time):
Вы компилируете код заранее. Весь "мертвый" код выкидывается. Остается только то, что реально используется.
• Плюс: Мгновенный старт (< 100ms), мизерное потребление памяти.
• Минус: Долгая сборка (build time), нет оптимизаций во время выполнения.
🛠 Как это выглядит на практике?
В Spring Boot 3 поддержка Native Image встроена официально.
1. Добавляем плагин (Gradle):
plugins {
id("org.springframework.boot") version "3.2.0"
id("org.graalvm.buildtools.native") version "0.9.28"
}
2. Собираем:
./gradlew nativeCompile
Внимание: Идите пить кофе. Сборка займет от 2 до 10 минут. GraalVM проводит статический анализ всего вашего кода и всех библиотек.
3. Запускаем:
./build/native/nativeCompile/my-app
> Started MyApp in 0.048 seconds (JVM running for 0.052)
Да, вы не ослышались. Spring Boot поднимается за 50 миллисекунд.
⚠️ Подводные камни (The Pain Points)
Не всё так радужно. Native Image ненавидит динамику.
1. Reflection API: GraalVM должен знать обо всех классах, которые вы загружаете через рефлексию, на этапе сборки. Раньше нужно было писать тонны JSON-конфигов. Сейчас Spring Boot делает это за вас, но сторонние либы могут сломаться.
2. Resources: Если вы читаете файл из
src/main/resources не стандартным способом, его может не оказаться в бинарнике.3. Нет "Write Once, Run Anywhere": Бинарник под Linux не запустится на Windows. Сборку нужно делать в той же OS (или в Docker-контейнере), где будет работать код.
📊 Когда использовать?
✅ Serverless (AWS Lambda, Google Cloud Run): Холодный старт больше не проблема.
✅ CLI утилиты: Консольные тулзы на Java теперь работают мгновенно.
✅ Kubernetes (Scale to Zero): Поды поднимаются и умирают за секунды, экономя ресурсы.
⛔ Обычные микросервисы (High Load): Если сервис живет месяцами и молотит тысячи запросов в секунду, обычная JVM (JIT) обгонит Native Image по пропускной способности (Throughput) за счет рантайм-оптимизаций.
#GraalVM #NativeImage #JavaPerformance #SpringBoot3 #Serverless
👉 @java_geek
👍2🔥2❤1
🏗 Java: Структурная конкурентность. Прощайте, зомби-потоки!
Допустим, вы используете Виртуальные потоки (Project Loom), чтобы сделать два независимых запроса: получить данные пользователя (API 1) и его заказы (API 2).
Раньше мы использовали
🧟♂️ Проблема зомби-потоков (Unstructured Concurrency)
Если API 1 мгновенно падает с ошибкой 500, ваш метод все равно будет ждать, пока API 2 доработает (или упадет по таймауту). Поток, качающий заказы, становится "сиротой". Он делает бесполезную работу, тратит сеть и память, хотя результат уже никому не нужен.
А если ошибку выкинет родительский метод? Дочерние потоки продолжат жить своей жизнью в фоне. Это хаос.
🧩 Решение:
В современной Java (начиная с 21 версии) потоки привязали к лексической области видимости - блоку кода. Если мы выходим из блока (из-за ошибки или успешного завершения), все запущенные внутри него дочерние потоки автоматически отменяются (получают
Вот как выглядит "Запрос-Ответ", где должны выполниться оба действия (Стратегия *All or Nothing*):
🏎 Стратегия "Кто первый, тот и прав"
А что, если вам нужно получить курс валют, и у вас есть 3 разных провайдера? Вам нужен ответ от любого, кто ответит быстрее.
Как только Банк А ответит, запросы к Банкам B и C будут немедленно отменены. Никакого ручного управления
🧠 Почему это меняет всё?
1. Читаемость: Многопоточный код читается сверху вниз, как обычный синхронный.
2. Безопасность ресурсов: Утечки потоков физически невозможны. Структура гарантирует, что родитель не завершится, пока не разберется со всеми детьми.
3. Идеальные логи: Стек-трейс теперь показывает реальную иерархию (кто кого вызвал), а не обрывается на внутренностях пула потоков.
В связке с Виртуальными потоками это делает Java одним из самых удобных языков для написания высоконагруженных сетевых приложений.
#Concurrency #ProjectLoom #CleanCode #Backend
👉 @java_geek
Допустим, вы используете Виртуальные потоки (Project Loom), чтобы сделать два независимых запроса: получить данные пользователя (API 1) и его заказы (API 2).
Раньше мы использовали
ExecutorService или CompletableFuture. Но у них есть огромная архитектурная дыра: они ничего не знают друг о друге.🧟♂️ Проблема зомби-потоков (Unstructured Concurrency)
Если API 1 мгновенно падает с ошибкой 500, ваш метод все равно будет ждать, пока API 2 доработает (или упадет по таймауту). Поток, качающий заказы, становится "сиротой". Он делает бесполезную работу, тратит сеть и память, хотя результат уже никому не нужен.
А если ошибку выкинет родительский метод? Дочерние потоки продолжат жить своей жизнью в фоне. Это хаос.
🧩 Решение:
StructuredTaskScopeВ современной Java (начиная с 21 версии) потоки привязали к лексической области видимости - блоку кода. Если мы выходим из блока (из-за ошибки или успешного завершения), все запущенные внутри него дочерние потоки автоматически отменяются (получают
interrupt).Вот как выглядит "Запрос-Ответ", где должны выполниться оба действия (Стратегия *All or Nothing*):
// ShutdownOnFailure: если один упал, отменяем остальные
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// Запускаем подзадачи (Subtasks)
Subtask<User> user = scope.fork(() -> fetchUser(id));
Subtask<List<Order>> orders = scope.fork(() -> fetchOrders(id));
scope.join(); // Ждем завершения обеих задач...
scope.throwIfFailed(); // ...или первой же ошибки!
// Сюда дойдем, только если обе задачи успешны
return new UserProfile(user.get(), orders.get());
}
// При выходе из блока любые зависшие потоки будут убиты
🏎 Стратегия "Кто первый, тот и прав"
А что, если вам нужно получить курс валют, и у вас есть 3 разных провайдера? Вам нужен ответ от любого, кто ответит быстрее.
// ShutdownOnSuccess: первый успешный отменяет остальные
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<Quote>()) {
scope.fork(() -> getFromBankA());
scope.fork(() -> getFromBankB());
scope.fork(() -> getFromBankC());
scope.join(); // Ждем первого успешного
return scope.result(); // Возвращаем самый быстрый ответ
}
Как только Банк А ответит, запросы к Банкам B и C будут немедленно отменены. Никакого ручного управления
Future.cancel(). Всё работает из коробки.🧠 Почему это меняет всё?
1. Читаемость: Многопоточный код читается сверху вниз, как обычный синхронный.
2. Безопасность ресурсов: Утечки потоков физически невозможны. Структура гарантирует, что родитель не завершится, пока не разберется со всеми детьми.
3. Идеальные логи: Стек-трейс теперь показывает реальную иерархию (кто кого вызвал), а не обрывается на внутренностях пула потоков.
В связке с Виртуальными потоками это делает Java одним из самых удобных языков для написания высоконагруженных сетевых приложений.
#Concurrency #ProjectLoom #CleanCode #Backend
👉 @java_geek
👍4🔥4❤3
🌉 Project Panama. Как вызвать C/C++ без боли?
Java долгое время жила в изоляции. Чтобы выйти за пределы JVM (вызвать функцию из OS, использовать библиотеку ML на C++ или графику на Rust), нам приходилось писать "клей" (glue code) на C.
Project Panama (Foreign Function & Memory API) меняет парадигму. Теперь Java умеет говорить с нативным кодом напрямую.
🗑 Что мы выбрасываем (JNI)
1. Больше не нужно писать ни строчки на C/C++.
2. Больше нет утилиты
3. Больше нет риска, что
✨ Как это работает (FFM API)
Допустим, мы хотим вызвать стандартную функцию
Шаг 1. Находим библиотеку
Шаг 2. Описываем сигнатуру (Descriptor)
Мы говорим Java: "Эта функция принимает указатель (Адрес) и возвращает число (long)".
Шаг 3. Выделяем память и вызываем
Самое интересное: мы аллоцируем память вне Java кучи (Off-heap) безопасным способом через
🤖 Killer Feature:
Вы скажете: "Писать дескрипторы для каждой функции вручную? Это же муторно!"
И вы правы. Поэтому есть утилита jextract.
Вы просто "скармливаете" ей заголовочный файл
Она сама сгенерирует все Java-классы и методы. Вы просто пишете:
Это выглядит и работает как обычный Java-код, но под капотом вызывает OpenGL напрямую.
🧠 Зачем это нужно?
1. AI и ML: TensorFlow, PyTorch, OpenCV - все они написаны на C++. Теперь Java может использовать их без тормозов JNI.
2. Базы данных: Драйверы могут работать напрямую с сетевым стеком OS (io_uring).
3. Rust: Вы можете написать критически важную логику на Rust, скомпилировать в библиотеку и использовать в Java.
🏆 Итог серии Modern Java
• Она запускается мгновенно (GraalVM).
• Она держит миллионы соединений (Virtual Threads).
• Она безопасна и лаконична (Records, Sealed Classes).
• Она открыта миру (Panama).
#ProjectPanama #FFM #Native #Performance
👉 @java_geek
Java долгое время жила в изоляции. Чтобы выйти за пределы JVM (вызвать функцию из OS, использовать библиотеку ML на C++ или графику на Rust), нам приходилось писать "клей" (glue code) на C.
Project Panama (Foreign Function & Memory API) меняет парадигму. Теперь Java умеет говорить с нативным кодом напрямую.
🗑 Что мы выбрасываем (JNI)
1. Больше не нужно писать ни строчки на C/C++.
2. Больше нет утилиты
javah.3. Больше нет риска, что
Unsafe удалят и ваш код сломается.✨ Как это работает (FFM API)
Допустим, мы хотим вызвать стандартную функцию
strlen из библиотеки C, чтобы узнать длину строки.Шаг 1. Находим библиотеку
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
// Ищем адрес функции "strlen" в памяти процесса
MemorySegment strlenAddress = stdlib.find("strlen").orElseThrow();
Шаг 2. Описываем сигнатуру (Descriptor)
Мы говорим Java: "Эта функция принимает указатель (Адрес) и возвращает число (long)".
FunctionDescriptor descriptor = FunctionDescriptor.of(
ValueLayout.JAVA_LONG, // Возвращаемое значение
ValueLayout.ADDRESS // Аргумент (указатель на строку)
);
MethodHandle strlen = linker.downcallHandle(strlenAddress, descriptor);
Шаг 3. Выделяем память и вызываем
Самое интересное: мы аллоцируем память вне Java кучи (Off-heap) безопасным способом через
Arena.
try (Arena arena = Arena.ofConfined()) {
// Превращаем Java String в C-строку (char*)
MemorySegment cString = arena.allocateFrom("Hello Panama!");
// Вызываем функцию C прямо из Java!
long length = (long) strlen.invoke(cString);
System.out.println(length); // 13
}
// Тут память автоматически очищается (как free() в C)
🤖 Killer Feature:
jextractВы скажете: "Писать дескрипторы для каждой функции вручную? Это же муторно!"
И вы правы. Поэтому есть утилита jextract.
Вы просто "скармливаете" ей заголовочный файл
.h:
jextract --output src -t org.example.opengl /usr/include/GL/gl.h
Она сама сгенерирует все Java-классы и методы. Вы просто пишете:
gl.glClear(gl.GL_COLOR_BUFFER_BIT());
Это выглядит и работает как обычный Java-код, но под капотом вызывает OpenGL напрямую.
🧠 Зачем это нужно?
1. AI и ML: TensorFlow, PyTorch, OpenCV - все они написаны на C++. Теперь Java может использовать их без тормозов JNI.
2. Базы данных: Драйверы могут работать напрямую с сетевым стеком OS (io_uring).
3. Rust: Вы можете написать критически важную логику на Rust, скомпилировать в библиотеку и использовать в Java.
🏆 Итог серии Modern Java
• Она запускается мгновенно (GraalVM).
• Она держит миллионы соединений (Virtual Threads).
• Она безопасна и лаконична (Records, Sealed Classes).
• Она открыта миру (Panama).
#ProjectPanama #FFM #Native #Performance
👉 @java_geek
👍4❤1🤯1
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Купить рекламу: https://telega.in/m/i_odmin
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
👎4👍2
🏗 System Design: Эволюция архитектуры от 1 до 1 000 000 пользователей
Главная ошибка разработчиков при проектировании систем - строить звездолет для поездки за хлебом. Микросервисы, Kafka и Kubernetes не нужны вашему стартапу в первый день.
Архитектура должна эволюционировать шаг за шагом. Вот как выглядит этот путь.
Уровень 1: Одинокий Волк (1 - 1000 юзеров)
Всё крутится на одном сервере (например, в DigitalOcean или AWS EC2).
• Что там: Ваше Java-приложение (Monolith) + база данных (PostgreSQL) + веб-сервер (Nginx) живут на одной машине.
• Плюсы: Развертывание занимает 5 минут, всё работает быстро (сетевые задержки нулевые).
• Минусы: Если сервер упал - упало всё. Масштабировать можно только покупкой более мощного процессора/памяти (Вертикальное масштабирование).
Уровень 2: Разделение труда (10 000 юзеров)
Приложение начинает тормозить, потому что СУБД "съела" всю оперативную память.
• Что делаем: Выносим базу данных на отдельный сервер. Желательно использовать управляемое решение (Managed DB от облачного провайдера), чтобы не возиться с бэкапами.
• Результат: Приложение и БД больше не дерутся за ресурсы.
Уровень 3: Горизонтальное масштабирование (100 000 юзеров)
Трафик растет. Один сервер приложения больше не справляется с HTTP-запросами.
• Что делаем: Ставим Load Balancer (Балансировщик нагрузки) и поднимаем 3-5 одинаковых серверов с вашим Java-приложением.
• Правило: Ваше приложение должно стать Stateless (без состояния). Вы больше не можете хранить сессии пользователей в локальной памяти (RAM), иначе юзер залогинится на Сервере 1, а следующий запрос попадет на Сервер 2, и его "выкинет". Сессии уезжают в централизованное хранилище.
Уровень 4: Спасаем базу данных (500 000 юзеров)
Приложений много, а БД одна. Она начинает "задыхаться" от количества чтений.
• Что делаем (Кэш): Ставим Redis или Memcached. До 80% запросов в типичном приложении - это чтение одних и тех же данных. Кэш отдает их за миллисекунды.
• Что делаем (Репликация): Разделяем БД на Master (для записи) и несколько Slave/Replica (только для чтения).
Уровень 5: Асинхронность и Очереди (1 000 000+ юзеров)
Пользователи жалуются, что загрузка отчета или обработка видео занимает слишком много времени, а HTTP-соединения отваливаются по таймауту.
• Что делаем: Внедряем брокер сообщений (Kafka или RabbitMQ) и создаем воркеры.
• Как это работает: Юзер жмет "сгенерировать отчет". Приложение кидает задачу в Kafka и мгновенно отвечает юзеру: "В процессе". А фоновые серверы-воркеры не спеша забирают задачи из очереди и делают тяжелую работу.
🧠 Главный принцип System Design
Не усложняйте систему до тех пор, пока метрики не покажут, что текущий уровень больше не справляется. Каждое усложнение (Load Balancer, Redis, Kafka) несет за собой новые проблемы: инвалидация кэша, задержки сети, дублирование сообщений.
#SystemDesign #Architecture #Backend #Scaling
👉 @java_geek
Главная ошибка разработчиков при проектировании систем - строить звездолет для поездки за хлебом. Микросервисы, Kafka и Kubernetes не нужны вашему стартапу в первый день.
Архитектура должна эволюционировать шаг за шагом. Вот как выглядит этот путь.
Уровень 1: Одинокий Волк (1 - 1000 юзеров)
Всё крутится на одном сервере (например, в DigitalOcean или AWS EC2).
• Что там: Ваше Java-приложение (Monolith) + база данных (PostgreSQL) + веб-сервер (Nginx) живут на одной машине.
• Плюсы: Развертывание занимает 5 минут, всё работает быстро (сетевые задержки нулевые).
• Минусы: Если сервер упал - упало всё. Масштабировать можно только покупкой более мощного процессора/памяти (Вертикальное масштабирование).
Уровень 2: Разделение труда (10 000 юзеров)
Приложение начинает тормозить, потому что СУБД "съела" всю оперативную память.
• Что делаем: Выносим базу данных на отдельный сервер. Желательно использовать управляемое решение (Managed DB от облачного провайдера), чтобы не возиться с бэкапами.
• Результат: Приложение и БД больше не дерутся за ресурсы.
Уровень 3: Горизонтальное масштабирование (100 000 юзеров)
Трафик растет. Один сервер приложения больше не справляется с HTTP-запросами.
• Что делаем: Ставим Load Balancer (Балансировщик нагрузки) и поднимаем 3-5 одинаковых серверов с вашим Java-приложением.
• Правило: Ваше приложение должно стать Stateless (без состояния). Вы больше не можете хранить сессии пользователей в локальной памяти (RAM), иначе юзер залогинится на Сервере 1, а следующий запрос попадет на Сервер 2, и его "выкинет". Сессии уезжают в централизованное хранилище.
Уровень 4: Спасаем базу данных (500 000 юзеров)
Приложений много, а БД одна. Она начинает "задыхаться" от количества чтений.
• Что делаем (Кэш): Ставим Redis или Memcached. До 80% запросов в типичном приложении - это чтение одних и тех же данных. Кэш отдает их за миллисекунды.
• Что делаем (Репликация): Разделяем БД на Master (для записи) и несколько Slave/Replica (только для чтения).
Уровень 5: Асинхронность и Очереди (1 000 000+ юзеров)
Пользователи жалуются, что загрузка отчета или обработка видео занимает слишком много времени, а HTTP-соединения отваливаются по таймауту.
• Что делаем: Внедряем брокер сообщений (Kafka или RabbitMQ) и создаем воркеры.
• Как это работает: Юзер жмет "сгенерировать отчет". Приложение кидает задачу в Kafka и мгновенно отвечает юзеру: "В процессе". А фоновые серверы-воркеры не спеша забирают задачи из очереди и делают тяжелую работу.
🧠 Главный принцип System Design
Не усложняйте систему до тех пор, пока метрики не покажут, что текущий уровень больше не справляется. Каждое усложнение (Load Balancer, Redis, Kafka) несет за собой новые проблемы: инвалидация кэша, задержки сети, дублирование сообщений.
#SystemDesign #Architecture #Backend #Scaling
👉 @java_geek
👍5❤1
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Купить рекламу: https://telega.in/m/i_odmin
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
❤2👍1👎1
В чем отличия между TreeSet и HashSet?
Основное отличие между
👉 @java_geek
Основное отличие между
TreeSet и HashSet заключается в том, что TreeSet хранит элементы в отсортированном порядке, в то время как порядок хранения элементов в HashSet не определен. TreeSet также обеспечивает быстрый поиск и извлечение элементов в отсортированном порядке.👉 @java_geek
👍3❤1
⚖️ System Design: Балансировщик нагрузки (Load Balancer). Как не уронить сервера?
В прошлом посте мы поняли, что один сервер не справляется, и запустили еще три таких же. Но как пользователи узнают, к какому из них подключаться? Не выдавать же им три разных IP-адреса!
Здесь на сцену выходит Load Balancer (LB) - регулировщик вашего трафика.
LB становится единственной точкой входа. Он принимает на себя все запросы от пользователей и по-умному раскидывает их по вашим серверам. Но как именно он решает, куда отправить следующий запрос? Для этого есть алгоритмы.
🧠 Главные алгоритмы балансировки
1. Round Robin (Карусель)
Самый простой и популярный по умолчанию. Запросы раздаются по кругу: первому серверу, второму, третьему, снова первому.
• Плюсы: Легко настроить, нулевая нагрузка на сам LB.
• Минусы: Слепой алгоритм. Если 1-й сервер завис, генерируя тяжелый отчет, а 2-й свободен, LB всё равно кинет им запросы поровну. 1-й сервер умрет окончательно.
2. Least Connections (Кто свободнее?)
LB работает как умный менеджер: он считает, сколько активных соединений висит на каждом сервере прямо сейчас. Новый запрос летит туда, где меньше всего работы.
• Идеально для: Приложений с долгими соединениями (чаты на WebSockets, потоковая передача видео, скачивание файлов).
3. IP Hash (Липкие сессии / Sticky Sessions)
LB берет IP-адрес пользователя, прогоняет через хэш-функцию и привязывает этот IP к конкретному серверу.
• Зачем нужно: Если ваше (легаси) приложение хранит корзину товаров в оперативной памяти конкретного сервера, вам критически важно, чтобы юзер всегда попадал на один и тот же сервер. Иначе на следующем клике его корзина "опустеет".
• Современный совет: Старайтесь избегать Sticky Sessions. Храните сессии в Redis, чтобы любой сервер мог обработать любой запрос.
4. Weighted алгоритмы (Система весов)
У вас в кластере два сервера: новый 32-ядерный монстр и старенькая 4-ядерная виртуалка. Если включить обычный Round Robin, старый сервер сгорит.
Вы задаете им "веса" (например, 8 и 1). Теперь мощный сервер будет получать 8 запросов на каждый 1 запрос к слабому.
🛠 Суперспособности балансировщиков
LB - это не только про алгоритмы. У него есть еще две критически важные функции:
• 🩺 Health Checks (Проверка пульса): Балансировщик постоянно "пингует" свои сервера (например, запрашивает
• 🔒 SSL Termination: Расшифровка HTTPS-трафика отнимает много ресурсов процессора. Балансировщик может взять эту тяжелую криптографию на себя. Он расшифровывает запрос, а дальше внутри вашей приватной (безопасной) сети общается с серверами по быстрому и легкому HTTP.
#SystemDesign #Backend #LoadBalancer #Architecture #DevOps
👉 @java_geek
В прошлом посте мы поняли, что один сервер не справляется, и запустили еще три таких же. Но как пользователи узнают, к какому из них подключаться? Не выдавать же им три разных IP-адреса!
Здесь на сцену выходит Load Balancer (LB) - регулировщик вашего трафика.
LB становится единственной точкой входа. Он принимает на себя все запросы от пользователей и по-умному раскидывает их по вашим серверам. Но как именно он решает, куда отправить следующий запрос? Для этого есть алгоритмы.
🧠 Главные алгоритмы балансировки
1. Round Robin (Карусель)
Самый простой и популярный по умолчанию. Запросы раздаются по кругу: первому серверу, второму, третьему, снова первому.
• Плюсы: Легко настроить, нулевая нагрузка на сам LB.
• Минусы: Слепой алгоритм. Если 1-й сервер завис, генерируя тяжелый отчет, а 2-й свободен, LB всё равно кинет им запросы поровну. 1-й сервер умрет окончательно.
2. Least Connections (Кто свободнее?)
LB работает как умный менеджер: он считает, сколько активных соединений висит на каждом сервере прямо сейчас. Новый запрос летит туда, где меньше всего работы.
• Идеально для: Приложений с долгими соединениями (чаты на WebSockets, потоковая передача видео, скачивание файлов).
3. IP Hash (Липкие сессии / Sticky Sessions)
LB берет IP-адрес пользователя, прогоняет через хэш-функцию и привязывает этот IP к конкретному серверу.
• Зачем нужно: Если ваше (легаси) приложение хранит корзину товаров в оперативной памяти конкретного сервера, вам критически важно, чтобы юзер всегда попадал на один и тот же сервер. Иначе на следующем клике его корзина "опустеет".
• Современный совет: Старайтесь избегать Sticky Sessions. Храните сессии в Redis, чтобы любой сервер мог обработать любой запрос.
4. Weighted алгоритмы (Система весов)
У вас в кластере два сервера: новый 32-ядерный монстр и старенькая 4-ядерная виртуалка. Если включить обычный Round Robin, старый сервер сгорит.
Вы задаете им "веса" (например, 8 и 1). Теперь мощный сервер будет получать 8 запросов на каждый 1 запрос к слабому.
🛠 Суперспособности балансировщиков
LB - это не только про алгоритмы. У него есть еще две критически важные функции:
• 🩺 Health Checks (Проверка пульса): Балансировщик постоянно "пингует" свои сервера (например, запрашивает
/health). Если сервер не ответил 3 раза подряд, LB помечает его как "мертвый" и перестает слать на него трафик. Пользователи даже не заметят, что один из серверов сгорел.• 🔒 SSL Termination: Расшифровка HTTPS-трафика отнимает много ресурсов процессора. Балансировщик может взять эту тяжелую криптографию на себя. Он расшифровывает запрос, а дальше внутри вашей приватной (безопасной) сети общается с серверами по быстрому и легкому HTTP.
#SystemDesign #Backend #LoadBalancer #Architecture #DevOps
👉 @java_geek
❤3👍2
🗑️ Java Garbage Collector: Кто убирает за вами мусор?
Разработчики на C и C++ живут в постоянном страхе утечек памяти: выделил память через
Всю грязную работу делает Garbage Collector (Сборщик мусора или просто GC). Но если не понимать, как он работает, ваше приложение однажды просто "зависнет" на пару секунд на продакшене.
🛑 Главная проблема: Stop-The-World
GC не может убирать мусор, пока ваше приложение активно меняет ссылки на объекты. Ему нужно поставить всё на паузу. Эта пауза называется Stop-The-World (STW).
В этот момент все ваши потоки замирают, пользователи видят "колесико загрузки", а запросы по сети отваливаются по таймауту. Вся эволюция GC в Java - это борьба за уменьшение этих пауз.
🧬 Гипотеза поколений
Как GC понимает, что удалять? Он опирается на одно гениальное наблюдение: 98% объектов умирают молодыми. (Например, локальные переменные внутри метода живут доли секунды).
Поэтому память (Heap) поделили на две части:
1. Young Generation (Молодое поколение): Сюда попадают все новые объекты. Очистка здесь происходит часто и невероятно быстро (Minor GC).
2. Old Generation (Старое поколение): Сюда "переезжают" объекты-долгожители (например, закэшированные данные или синглтоны Spring). Очистка здесь происходит редко, но занимает много времени (Major/Full GC).
🥊 Битва титанов: Какой GC выбрать?
В современных версиях Java вам, как правило, нужно знать о двух главных сборщиках.
1. G1 (Garbage-First)
• Статус: Включен по умолчанию с Java 9.
• Как работает: Дробит память на сотни мелких регионов. Во время уборки он смотрит: "Ага, вот в этом регионе 90% мусора, начну с него" (отсюда и название - мусор в первую очередь).
• Кому подходит: 95% обычных веб-приложений. Он отлично балансирует между высокой пропускной способностью и приемлемыми паузами (целевая пауза по умолчанию — 200 мс).
2. ZGC (Z Garbage Collector)
• Статус: Готов к бою (Production Ready) с Java 15, а в Java 21 стал генерационным.
• Как работает: Настоящая магия и инженерное чудо. ZGC выполняет почти всю работу параллельно с вашим приложением, используя "цветные указатели" (colored pointers).
• Суперсила: Паузы Stop-The-World не превышают 1 миллисекунды, даже если у вас куча (Heap) размером в 16 Терабайт!
• Кому подходит: Финансовым биржам, игровым серверам и системам, где важна ультра-низкая задержка (Low Latency).
🛠 Как включить?
Ничего устанавливать не нужно, просто добавьте флаг при запуске
• Для G1 (если у вас старая Java):
• Для ZGC:
🧠 Золотое правило Memory Management
Сборщик мусора в Java невероятно умен. Не пытайтесь ему "помогать".
Вызовы
#Java #GarbageCollector #Performance #JVM #Backend
👉 @java_geek
Разработчики на C и C++ живут в постоянном страхе утечек памяти: выделил память через
malloc - обязан очистить через free. Мы же в Java просто пишем new Object() и идем пить кофе. Всю грязную работу делает Garbage Collector (Сборщик мусора или просто GC). Но если не понимать, как он работает, ваше приложение однажды просто "зависнет" на пару секунд на продакшене.
🛑 Главная проблема: Stop-The-World
GC не может убирать мусор, пока ваше приложение активно меняет ссылки на объекты. Ему нужно поставить всё на паузу. Эта пауза называется Stop-The-World (STW).
В этот момент все ваши потоки замирают, пользователи видят "колесико загрузки", а запросы по сети отваливаются по таймауту. Вся эволюция GC в Java - это борьба за уменьшение этих пауз.
🧬 Гипотеза поколений
Как GC понимает, что удалять? Он опирается на одно гениальное наблюдение: 98% объектов умирают молодыми. (Например, локальные переменные внутри метода живут доли секунды).
Поэтому память (Heap) поделили на две части:
1. Young Generation (Молодое поколение): Сюда попадают все новые объекты. Очистка здесь происходит часто и невероятно быстро (Minor GC).
2. Old Generation (Старое поколение): Сюда "переезжают" объекты-долгожители (например, закэшированные данные или синглтоны Spring). Очистка здесь происходит редко, но занимает много времени (Major/Full GC).
🥊 Битва титанов: Какой GC выбрать?
В современных версиях Java вам, как правило, нужно знать о двух главных сборщиках.
1. G1 (Garbage-First)
• Статус: Включен по умолчанию с Java 9.
• Как работает: Дробит память на сотни мелких регионов. Во время уборки он смотрит: "Ага, вот в этом регионе 90% мусора, начну с него" (отсюда и название - мусор в первую очередь).
• Кому подходит: 95% обычных веб-приложений. Он отлично балансирует между высокой пропускной способностью и приемлемыми паузами (целевая пауза по умолчанию — 200 мс).
2. ZGC (Z Garbage Collector)
• Статус: Готов к бою (Production Ready) с Java 15, а в Java 21 стал генерационным.
• Как работает: Настоящая магия и инженерное чудо. ZGC выполняет почти всю работу параллельно с вашим приложением, используя "цветные указатели" (colored pointers).
• Суперсила: Паузы Stop-The-World не превышают 1 миллисекунды, даже если у вас куча (Heap) размером в 16 Терабайт!
• Кому подходит: Финансовым биржам, игровым серверам и системам, где важна ультра-низкая задержка (Low Latency).
🛠 Как включить?
Ничего устанавливать не нужно, просто добавьте флаг при запуске
java -jar:• Для G1 (если у вас старая Java):
-XX:+UseG1GC• Для ZGC:
-XX:+UseZGC🧠 Золотое правило Memory Management
Сборщик мусора в Java невероятно умен. Не пытайтесь ему "помогать".
Вызовы
System.gc() в коде - это выстрел себе в ногу. Просто пишите чистый код, не держите ссылки на объекты, которые вам больше не нужны, и GC сделает всё сам.#Java #GarbageCollector #Performance #JVM #Backend
👉 @java_geek
👍4❤1
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Купить рекламу: https://telega.in/m/i_odmin
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
🖕3❤1
🧠 Почему
Один из самых частых вопросов: "Я поставил
📌 Ответ — в механизме прокси Spring.
Spring оборачивает бины с
💡 Пример:
📎 Решения:
1. Вынести метод в другой бин:
2. Или вызвать себя через
⚠️ Но лучше использовать первый способ — он чище архитектурно.
👉 @java_geek
@Transactional не работает?Один из самых частых вопросов: "Я поставил
@Transactional, но транзакция не откатывается. Почему?"📌 Ответ — в механизме прокси Spring.
Spring оборачивает бины с
@Transactional в прокси, которые перехватывают вызовы и управляют транзакцией. Но работает это только при вызове метода извне. Если ты вызываешь метод с @Transactional внутри того же класса, прокси не используется, и аннотация игнорируется.💡 Пример:
@Service
public class UserService {
public void registerUser() {
createUser(); // ❌ Транзакция не работает!
}
@Transactional
public void createUser() {
// изменения в БД
}
}
📎 Решения:
1. Вынести метод в другой бин:
@Service
public class UserService {
private final UserWriter writer;
public UserService(UserWriter writer) {
this.writer = writer;
}
public void registerUser() {
writer.createUser(); // ✅ работает
}
}
@Service
public class UserWriter {
@Transactional
public void createUser() {
// изменения в БД
}
}
2. Или вызвать себя через
ApplicationContext:
@Autowired
private ApplicationContext context;
public void registerUser() {
context.getBean(UserService.class).createUser(); // ✅ работает
}
⚠️ Но лучше использовать первый способ — он чище архитектурно.
👉 @java_geek
👍2❤1
Fluent Interface
Fluent Interface (Текучий интерфейс) — это шаблон проектирования, который позволяет создавать код, читающийся как текст на естественном языке.
Он достигается путем создания методов, которые возвращают ссылку на this объект, позволяя вызывать их в цепочке.
👉 @java_geek
Fluent Interface (Текучий интерфейс) — это шаблон проектирования, который позволяет создавать код, читающийся как текст на естественном языке.
Он достигается путем создания методов, которые возвращают ссылку на this объект, позволяя вызывать их в цепочке.
👉 @java_geek
❤2👍2
🧠 Зачем использовать
Многие добавляют
📌 Что делает
* Подсказывает JPA провайдеру (например, Hibernate), что изменения в сущностях можно не отслеживать (
* В некоторых БД может выставить read-only transaction flag, который предотвращает нежелательные изменения (например, в PostgreSQL).
* Может ускорить выборки, особенно при больших графах сущностей.
💡 Пример:
⚠️ Важно:
*
* Hibernate всё равно создаст транзакцию — это не аннотация "без транзакций".
✅ Когда использовать:
* Методы, которые только читают данные и не модифицируют сущности.
* Большие выборки без нужды в lazy-инициализации через сессию.
* Там, где критична производительность чтения.
❌ Когда НЕ нужно:
* Если вы всё равно модифицируете сущности внутри метода.
* Если работаете с
📎 Документация Spring @Transactional
👉 @java_geek
@Transactional(readOnly = true)?Многие добавляют
@Transactional(readOnly = true) на сервисные методы просто по привычке. Но давайте разберёмся, что на самом деле даёт этот флаг, и где он реально ускоряет выполнение.📌 Что делает
readOnly = true?* Подсказывает JPA провайдеру (например, Hibernate), что изменения в сущностях можно не отслеживать (
skip dirty checking).* В некоторых БД может выставить read-only transaction flag, который предотвращает нежелательные изменения (например, в PostgreSQL).
* Может ускорить выборки, особенно при больших графах сущностей.
💡 Пример:
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
@Transactional(readOnly = true)
public UserDto getUser(Long id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("User not found"));
return UserDto.from(user);
}
}
⚠️ Важно:
*
readOnly = true не блокирует изменения в БД, если вы явно вызываете save() — это НЕ защита от дурака.* Hibernate всё равно создаст транзакцию — это не аннотация "без транзакций".
✅ Когда использовать:
* Методы, которые только читают данные и не модифицируют сущности.
* Большие выборки без нужды в lazy-инициализации через сессию.
* Там, где критична производительность чтения.
❌ Когда НЕ нужно:
* Если вы всё равно модифицируете сущности внутри метода.
* Если работаете с
@Modifying запросами — Spring их игнорирует при readOnly = true.📎 Документация Spring @Transactional
👉 @java_geek
❤1👍1🔥1😱1
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
MAX
Bash Советы - Bash Scripting | Linux Terminal & Shell. Скри…
Укроти командную строку. Пишем эффективные Bash-скрипты для сервера и десктопа. Магия текстовой обработки: Grep, Sed, Awk и регулярные выражения (Regex). Настр…
🔥 Spring Native Image vs. Обычное Spring-приложение: В чем разница и зачем это нужно?
Разбираемся, как нативные образы меняют правила игры для Spring-приложений! 👇
Обычное Spring-приложение (JVM-based):
Когда вы запускаете классический Spring Boot на Java Virtual Machine (JVM), происходит следующее:
🔵 JVM запускается первой: Прежде чем ваш код заработает, JVM должна инициализироваться и загрузить классы. Это занимает время.
🔵 Динамическая природа: JVM позволяет динамически загружать классы и использовать рефлексию в рантайме. Это гибко, но ресурсозатратно.
🔵 "Прогрев" (Warm-up): Для пиковой производительности JVM нужно время на JIT-компиляцию кода.
🔵 Большой объем памяти: JVM сама по себе требует значительного объема RAM.
🔵 Размер артефакта: JAR-файл содержит байт-код, который JVM затем обрабатывает.
Spring Native Image (с GraalVM Native Image):
Это компиляция вашего Spring-приложения в самостоятельный нативный исполняемый файл, не требующий JVM!
🔵 Компиляция AOT (Ahead-of-Time): Весь код (включая Spring и JDK) компилируется в машинный код на этапе сборки. Все оптимизации происходят заранее.
🔵 Мгновенный старт: Нет JVM и "прогрева"! Нативные образы стартуют мгновенно (от долей секунды). Идеально для:
🔵 Серверлес-функций (Lambda, FaaS): Быстрый старт снижает задержки и стоимость.
🔵 Микросервисов: Для быстрого масштабирования.
🔵 Batch-задач: Быстрый запуск и завершение.
🔵 Низкое потребление памяти: Отсутствие JVM значительно сокращает RAM. Экономия облачных ресурсов и возможность запускать больше приложений на сервере.
🔵 Меньший размер образа: Включается только используемый код без JVM, что упрощает развертывание в контейнерах.
🔵 Статический анализ: GraalVM глубоко анализирует код, исключая неиспользуемые части.
Недостатки (куда без них?):
🔵 Длительное время сборки: AOT-компиляция занимает значительно больше времени.
🔵 Сложности с динамикой: Рефлексия и прокси требуют дополнительных настроек (runtime hints), хотя Spring Boot 3 упрощает это.
🔵 Отсутствие некоторых инструментов мониторинга: Привычные JVM-инструменты (JMX, JFR) не поддерживаются напрямую.
🔵 Специфичность платформы: Нужен отдельный образ для каждой ОС и архитектуры.
Когда стоит использовать Spring Native Image?
🔵 Когда время старта и потребление памяти критичны.
🔵 Для микросервисов, серверлес-функций и batch-задач.
🔵 Для контейнеров и облачных сред с оплатой по потреблению.
👉 @java_geek
Разбираемся, как нативные образы меняют правила игры для Spring-приложений! 👇
Обычное Spring-приложение (JVM-based):
Когда вы запускаете классический Spring Boot на Java Virtual Machine (JVM), происходит следующее:
Spring Native Image (с GraalVM Native Image):
Это компиляция вашего Spring-приложения в самостоятельный нативный исполняемый файл, не требующий JVM!
Недостатки (куда без них?):
Когда стоит использовать Spring Native Image?
👉 @java_geek
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1🥴1
🧠 Неожиданный анти-паттерн в Spring Boot:
В Spring удобно использовать
📌 По умолчанию все
Это значит:
А теперь представим, что слушатель делает что-то тяжёлое:
⚠️ Если
💡 Решение: сделать обработку асинхронной.
Просто добавьте
✅ И не забудьте включить поддержку
📌 Теперь
👉 @java_geek
@EventListener как тихий убийца производительностиВ Spring удобно использовать
@EventListener для реактивных действий — казалось бы, удобно и "чисто". Но есть нюанс.📌 По умолчанию все
@EventListener вызываются синхронно и в том же потоке, где был опубликован ивент через ApplicationEventPublisher.Это значит:
@Component
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 1. Сохраняем заказ
orderRepository.save(order);
// 2. Публикуем ивент
publisher.publishEvent(new OrderCreatedEvent(order));
// 3. До выхода из метода все @EventListener уже будут выполнены
}
}
А теперь представим, что слушатель делает что-то тяжёлое:
@EventListener
public void sendEmail(OrderCreatedEvent event) {
emailService.sendConfirmation(event.getOrder());
}
⚠️ Если
sendConfirmation висит на внешнем SMTP или уходит в сеть — метод createOrder будет ждать его завершения!💡 Решение: сделать обработку асинхронной.
Просто добавьте
@Async:
@Async
@EventListener
public void sendEmail(OrderCreatedEvent event) {
emailService.sendConfirmation(event.getOrder());
}
✅ И не забудьте включить поддержку
@Async:
@EnableAsync
@Configuration
public class AsyncConfig {}
📌 Теперь
@EventListener будет исполняться в отдельном потоке из TaskExecutor, и createOrder не будет блокироваться.👉 @java_geek
🔥2❤1👍1
🧠 Ленивая инициализация
По умолчанию Spring инициализирует все бины при старте приложения. Это удобно, но может замедлить запуск, особенно если есть тяжёлые компоненты — например, коннекторы к внешним сервисам, парсеры, или тяжёлые кэши.
📌 Решение — использовать ленивую инициализацию (
Теперь бин будет создан только при первом обращении.
Можно также внедрять лениво:
💡 Если у вас много таких компонентов — можно включить ленивую инициализацию глобально:
⚠️ Осторожно: это может скрыть ошибки конфигурации до первого использования бина, что усложняет отладку. Используйте осознанно.
Идеально подходит для:
— микросервисов с быстрым стартом
— CLI-инструментов на Spring Boot
— задач с heavy startup logic
👉 @java_geek
@Component в Spring BootПо умолчанию Spring инициализирует все бины при старте приложения. Это удобно, но может замедлить запуск, особенно если есть тяжёлые компоненты — например, коннекторы к внешним сервисам, парсеры, или тяжёлые кэши.
📌 Решение — использовать ленивую инициализацию (
@Lazy):
@Component
@Lazy
public class HeavyComponent {
public HeavyComponent() {
System.out.println("HeavyComponent инициализирован");
}
}
Теперь бин будет создан только при первом обращении.
Можно также внедрять лениво:
@Component
public class SomeService {
private final HeavyComponent heavy;
public SomeService(@Lazy HeavyComponent heavy) {
this.heavy = heavy;
}
}
💡 Если у вас много таких компонентов — можно включить ленивую инициализацию глобально:
spring:
main:
lazy-initialization: true
⚠️ Осторожно: это может скрыть ошибки конфигурации до первого использования бина, что усложняет отладку. Используйте осознанно.
Идеально подходит для:
— микросервисов с быстрым стартом
— CLI-инструментов на Spring Boot
— задач с heavy startup logic
👉 @java_geek
👍3
🚀 Подборка полезных IT каналов в Max
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
Системное администрирование, DevOps 📌
https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных
Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков
Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов
Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻
Шутки программистов 📌
https://max.ru/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free
Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров
Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Купить рекламу: https://telega.in/m/i_odmin
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
Объясните концепцию наследования в Java на примерах
Наследование — один из ключевых принципов объектно-ориентированного программирования в Java. Оно позволяет одному классу наследовать свойства и методы другого класса, что способствует повторному использованию кода и устанавливает отношение «родитель–потомок» между классами.
Например, класс
- Класс
- Класс
👉 @java_geek
Наследование — один из ключевых принципов объектно-ориентированного программирования в Java. Оно позволяет одному классу наследовать свойства и методы другого класса, что способствует повторному использованию кода и устанавливает отношение «родитель–потомок» между классами.
Например, класс
Car может наследоваться от общего класса Vehicle. В этом случае Car может вести себя так же, как Vehicle, с точки зрения атрибутов и методов:- Класс
Vehicle имеет такие члены, как year и make, а Car добавляет дополнительный член transmission.- Класс
Vehicle имеет метод move, а Car переопределяет move, добавляя поведение, характерное для автомобилей.👉 @java_geek
❤1👍1