uz
Feedback
Библиотека Java разработчика

Библиотека Java разработчика

Kanalga Telegram’da o‘tish

📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP

Ko'proq ko'rsatish

📈 Telegram kanali Библиотека Java разработчика analitikasi

Библиотека Java разработчика (@bookjava) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 10 278 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 12 030-o'rinni va Rossiya mintaqasida 63 913-o'rinni egallagan.

📊 Auditoriya ko‘rsatkichlari va dinamika

невідомо sanasidan buyon loyiha tez o‘sib, 10 278 obunachiga ega bo‘ldi.

05 Iyun, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni 20 ga, so‘nggi 24 soatda esa 0 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.

  • Tasdiqlash holati: Tasdiqlanmagan
  • Jalb etish (ER): Auditoriya o‘rtacha 8.29% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 3.77% ini tashkil etuvchi reaksiyalarni to‘playdi.
  • Post qamrovi: Har bir post o‘rtacha 852 marta ko‘riladi; birinchi sutkada odatda 388 ta ko‘rish yig‘iladi.
  • Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 6 ta reaksiya keladi.
  • Tematik yo‘nalishlar: Kontent string, интерфейс, строка, boot, api kabi asosiy mavzularga jamlangan.

📝 Tavsif va kontent siyosati

Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP

Yuqori yangilanish chastotasi (oxirgi ma’lumot 07 Iyun, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.

10 278
Obunachilar
Ma'lumot yo'q24 soatlar
+27 kunlar
+2030 kunlar
Postlar arxiv
🤖 Хотите автоматизировать инфраструктуру для тестирования прямо в Gradle? На открытом уроке «Облако в кармане: запускаем всю
🤖 Хотите автоматизировать инфраструктуру для тестирования прямо в Gradle? На открытом уроке «Облако в кармане: запускаем всю инфраструктуру для теста при сборке» от OTUS мы расскажем, как избежать ручных настроек и запусков. Вместо этого вы научитесь автоматизировать весь процесс с помощью Docker, DockerCompose и TestContainers, интегрируя их с Gradle. Урок полезен для разработчиков на Kotlin и Java, которые работают с автотестами — интеграционными и end-to-end. В ходе урока вы освоите: ▫️Автоматический запуск всей необходимой инфраструктуры для тестирования. ▫️Создание Docker-образов для тестов и деплоя. ▫️Разработку автотестов, которые поднимут ваши навыки на новый уровень. Участники получат скидку на курс «Kotlin Backend Developer. Professional». ➡️ Встречаемся 29 апреля в 20:00 МСК, регистрация открыта: https://vk.cc/cL78v6 Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🧠 JPA: подводный камень с @ElementCollection и fetch = FetchType.EAGER Сегодня покажу, почему @ElementCollection(fetch = Fet
🧠 JPA: подводный камень с @ElementCollection и fetch = FetchType.EAGER Сегодня покажу, почему @ElementCollection(fetch = FetchType.EAGER) — скрытая угроза производительности и неожиданного поведения. 📌 Суть проблемы При использовании @ElementCollection с EAGER Hibernate делает отдельный SELECT на каждую коллекцию, даже при JOIN FETCH на родительскую сущность.

@Entity
class User {
    @Id Long id;

    @ElementCollection(fetch = FetchType.EAGER)
    List<String> tags;
}
Запрос findAll() приведёт к N+1 проблеме: 1 запрос на User, потом по одному на каждый tags. 💡 Почему это больно Даже если вы используете JOIN FETCH на User, Hibernate не может сделать JOIN на @ElementCollection. Это ограничение — Hibernate всегда грузит коллекцию отдельным запросом. ⚠️ Особенно опасно при pagination Если вы делаете Page<User> — Hibernate сначала грузит User'ов, а затем делает N запросов на коллекции. В проде это быстро становится проблемой. ✅ Что делать 1. Делайте fetch = FetchType.LAZY (по умолчанию так и есть). 2. Если нужно подгрузить коллекцию — используйте @BatchSize:

@ElementCollection
@BatchSize(size = 20)
List<String> tags;
Или вручную:

SELECT u FROM User u LEFT JOIN FETCH u.tags WHERE u.id IN :ids
👉 Следи за @ElementCollection — он не так прост, как кажется. 👉@BookJava

🧠 Как избежать N+1 при использовании @OneToMany в JPA Одна из самых коварных ловушек JPA - это N+1 проблема. Особенно часто
🧠 Как избежать N+1 при использовании @OneToMany в JPA Одна из самых коварных ловушек JPA - это N+1 проблема. Особенно часто она проявляется при @OneToMany, например:

@Entity
class Author {
    @OneToMany(mappedBy = "author", fetch = FetchType.LAZY)
    private List<Book> books;
}
Вы загружаете список авторов, а потом проходите по каждому и вызываете getBooks() — и BAM 💥: 1 запрос на авторов и N запросов на книги. 📌 Решение - @EntityGraph или JOIN FETCH Оба варианта решают проблему, но @EntityGraph — декларативный и более гибкий способ:

@EntityGraph(attributePaths = "books")
List<Author> findAll(); // Spring Data JPA
⚡️ Или через JPQL:

@Query("SELECT a FROM Author a JOIN FETCH a.books")
List<Author> findAllWithBooks();
💡 Совет: всегда думайте о графе объектов. Если вам нужно сразу подтянуть связанные сущности — делайте это явно. Не надейтесь на LAZY по умолчанию. ⚠️ Осторожно с пагинацией и JOIN FETCH — могут появиться дубликаты или проблемы с LIMIT. В таких случаях лучше использовать @BatchSize или подзапросы. 👉@BookJava

👩‍💻 Разработка на Java требует глубокого понимания не только языка, но и принципов работы JVM, многопоточности и современны
👩‍💻 Разработка на Java требует глубокого понимания не только языка, но и принципов работы JVM, многопоточности и современных фреймворков. Курс «Java Developer. Professional» — это структурированное обучение для разработчиков, которые хотят выйти на новый уровень, освоить актуальный стек технологий и уверенно претендовать на позиции уровня Middle+. 🦾 Вы получите 96 часов практической работы, обучение на живых вебинарах, вы разберете ключевые аспекты работы JVM, научитесь строить эффективные многопоточные приложения, освоите Spring WebFlux, Kafka, реактивный Postgres и Kubernetes. Программа OTUS постоянно обновляется, соответствуя требованиям рынка, а диплом ценится работодателями. 👉 Пройдите вступительное тестирование и присоединяйтесь к группе: https://vk.cc/cL3cnt 🎁 Начните обучение со скидкой, подробности у менеджеров. ПРОМОКОД: JAVA_04 Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Чем отличаются checked и unchecked исключения в java? В Java исключения делятся на два основных типа: checked и unchecked. Ра
Чем отличаются checked и unchecked исключения в java? В Java исключения делятся на два основных типа: checked и unchecked. Разница между ними ключевая и касается как обработки, так и структуры кода. ✅ Checked Exceptions (Проверяемые исключения) Примеры: IOException, SQLException, FileNotFoundException Отличия: 1. Проверяются компилятором — вы обязаны либо обработать их с помощью try-catch, либо явно пробросить (throws) в сигнатуре метода. 2. Производные от Exception, но не от RuntimeException. 3. Используются для ситуаций, которые можно разумно ожидать и обработать (например, отсутствие файла, проблемы с сетью). Пример:

public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);  // может выбросить IOException
}
Unchecked Exceptions (Непроверяемые исключения) Примеры: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException Отличия: 1. Не проверяются компилятором — вы не обязаны их обрабатывать или декларировать. 2. Производные от RuntimeException. 3. Возникают в результате ошибок в логике программы или непредвиденных ситуаций. Пример:

public void printLength(String str) {
    System.out.println(str.length());  // может выбросить NullPointerException
}
Если кратко: Checked — ошибки среды, требующие явной обработки. Unchecked — ошибки в логике, ответственность программиста. 👉@BookJava

🧠 JPA: не забывай про flush() перед clear() — иначе словишь баг Если ты используешь EntityManager вручную, например, при батчевой вставке или обновлении, то, скорее всего, пишешь что-то вроде:

for (int i = 0; i < entities.size(); i++) {
    em.persist(entities.get(i));
    if (i % 50 == 0) {
        em.clear(); // чтобы не росла память
    }
}
⚠️ Но тут баг: без flush() перед clear() ты теряешь все неперсистенные изменения! Hibernate просто забудет про них. ✅ Правильно так:

for (int i = 0; i < entities.size(); i++) {
    em.persist(entities.get(i));
    if (i % 50 == 0) {
        em.flush();
        em.clear();
    }
}
📌 flush() гарантирует, что все накопленные изменения пойдут в базу, а clear() уже безопасно очищает контекст. 💡 Эта ошибка особенно коварна, потому что не всегда проявляется — зависит от настроек, триггеров в БД, кэша и т.д. 👉@BookJava

Осталось всего 2 дня — углубитесь в функциональное программирование на Scala в Otus 📢 24 апреля в 20:00 пройдёт открытый веб
Осталось всего 2 дня — углубитесь в функциональное программирование на Scala в Otus 📢 24 апреля в 20:00 пройдёт открытый вебинар с Алексеем Воронцом — руководителем разработки в Naumen, 14 лет опыта, из них 9 лет на Scala. Он расскажет: — почему Scala — функциональный язык — как работать с ключевыми библиотеками — как повысить выразительность кода Если вы уже знакомы со Scala или желаете перейти на него и хотите развивать функциональный подход в своих проектах — этот вебинар для вас. Каждый участник: — сможет задать вопросы эксперту — получит скидку на полный курс по Scala-разработке 👉 Не упустите возможность перейти на новый уровень — регистрируйтесь, осталось 2 дня до начала Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

🧠 Spring Boot и медленные autowire — проверь, не зарыта ли у тебя бомба в @Configuration Есть распространённый анти-паттерн: ты используешь @Configuration и внутри создаёшь бины с @Bean, а в этих методах — инжектишь зависимости через параметры. Всё выглядит красиво и «по фэншую»... но только на первый взгляд.

@Configuration
public class MyConfig {

    @Bean
    public MyService myService(SomeDep dep) {
        return new MyService(dep);
    }

    @Bean
    public SomeDep someDep() {
        return new SomeDep();
    }
}
⚠️ Проблема: такие методы вызываются при старте контекста, и если SomeDep создаётся долго (например, подтягивает настройки из удалённого конфига, делает init-запрос в БД, или тянет секьюрити-контекст), это тормозит весь старт. 📌 Хуже всего, если ты не подозреваешь об этом: ведь @Bean -методы не видны как "инициализация", и кажется, что контекст тормозит "где-то ещё". 💡 Совет: - Используй @Lazy в нужных местах, особенно если bean тяжёлый или редко используется. - Разделяй конфигурацию: отдельно core, отдельно init-heavy. - Не бойся отказаться от @Configuration в пользу @Component + @Service, если это упрощает понимание. И главное — профилируй старт. spring-boot-starter-actuator + --debug могут открыть глаза. 👉@BookJava

23 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Mid
23 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Илья Аров, старший разработчик в Т1, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Илья будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Илье Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.  Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzqvv6bu4

🧠 Spring Boot 3.2+: ускоряем стартап с помощью application.metrics.export.observation.enabled=false Spring Boot 3.2 по умолчанию включает сбор Micrometer Observation метрик — даже если вы не используете Prometheus, Datadog и пр. Это полезно, но часто избыточно — особенно в микросервисах, где важна скорость старта. 📌 Что это даёт? - Отключает автоконфигурацию ObservationRegistry - Убирает связанные Bean'ы - Сокращает время старта до 30-60% (в зависимости от контекста) 💡 Как применить? В application.yml или application.properties:

management:
  metrics:
    export:
      observation:
        enabled: false
Или так, если используешь .properties:

management.metrics.export.observation.enabled=false
⚠️ Важно: это не отключает другие метрики Micrometer. Это касается только новой подсистемы Observation — она полезна для трассировки, но не всегда нужна. 📎 Документация Micrometer Observation 👉@BookJava

🧠 Lazy Initialization по-взрослому: не создавай проблемы на ровном месте В Spring Boot часто можно встретить вот такую конструкцию:

@Service
public class EmailService {
    private final SmtpClient client = new SmtpClient(); // дорогая инициализация
}
⚠️ Проблема: SmtpClient создаётся сразу при старте приложения. Даже если EmailService ни разу не вызовется. Это не только waste of resources, но и может сломать запуск, если SmtpClient требует специфического окружения. 📌 Решение — ленивая инициализация, но не через старый добрый null-check, а красиво, безопасно и читаемо: 💡 Способ #1: Lazy<T> wrapper

@Component
public class EmailService {
    private final Supplier<SmtpClient> client = Suppliers.memoize(SmtpClient::new);

    public void sendEmail(...) {
        client.get().send(...);
    }
}
Можно и без Guava:

public class Lazy<T> {
    private Supplier<T> supplier;

    public Lazy(Supplier<T> supplier) {
        this.supplier = () -> {
            T value = supplier.get();
            this.supplier = () -> value;
            return value;
        };
    }

    public T get() {
        return supplier.get();
    }
}
💡 Способ #2: через Spring

@Service
public class EmailService {
    private final ObjectProvider<SmtpClient> client;

    public EmailService(ObjectProvider<SmtpClient> client) {
        this.client = client;
    }

    public void sendEmail(...) {
        client.getObject().send(...);
    }
}
🧵 Итог: - Не инициализируй тяжёлые объекты зря. - Используй Supplier, ObjectProvider или Lazy<T>. - Это особенно критично для тестов, лямбд и кэширования. 👉@BookJava

Реальные проекты и нетворкинг с профи: Летняя школа бэкенд‑разработки Яндекса открыла набор Начинающие бэкендеры, есть планы
Реальные проекты и нетворкинг с профи: Летняя школа бэкенд‑разработки Яндекса открыла набор Начинающие бэкендеры, есть планы на лето? Если уже умеете писать читаемый код в Python, Java или C++ и разбираетесь в алгоритмах, Летняя школа бэкенда Яндекса — ваш шанс прокачаться в разработке высоконагруженных сервисов. Вы получите уникальный опыт, работая вместе с ведущими специалистами компании. Как проходит обучение: — со 2 июня по 27 июля — онлайн-лекции, семинары и практические задания — с 28 июля по 24 августа — разработка реальных проектов офлайн или онлайн Вас ждут: — работа в фулстек-командах в коворкингах Яндекса — лекции от специалистов компании в летнем лектории — возможность стать частью команды и получить офер: больше половины выпускников становятся стажерами или сотрудниками компании Школа бесплатная, но нужно пройти отбор. Отправляй заявку до 27 апреля!

🧠 Сейчас покажу баг, который легко пропустить при работе с @Transactional в Spring Boot 3+. 📌 Проблема — транзакция не рабо
🧠 Сейчас покажу баг, который легко пропустить при работе с @Transactional в Spring Boot 3+. 📌 Проблема — транзакция не работает, потому что метод вызывается изнутри того же класса. Рассмотрим пример:

@Service
public class UserService {

    @Transactional
    public void createUser(User user) {
        saveUser(user);
        sendWelcomeEmail(user); // бросает исключение
    }

    public void saveUser(User user) {
        userRepository.save(user);
    }
}
💥 Если sendWelcomeEmail выбросит исключение — транзакция не откатится, потому что @Transactional работает через прокси. Вызов createUser() должен идти извне, чтобы Spring "знал", что нужно обернуть вызов в транзакцию. ✅ Решения: 1. Вынести transactional-метод в отдельный бин:

   @Service
   public class UserCreationService {
       @Transactional
       public void createUser(User user) {
           // ...
       }
   }
   
2. Внедрить self-прокси:

   @Autowired
   private UserService self;

   public void externalCaller(User user) {
       self.createUser(user);
   }
   
3. Использовать AopContext:

   ((UserService) AopContext.currentProxy()).createUser(user);
   
⚠️ Не забудь включить exposeProxy = true в @EnableAspectJAutoProxy. 💡 Современный подход — разделение ответственности: transactional-методы живут в отдельных сервисах, их проще тестировать и не возникает подобных ловушек. 👉@BookJava

Хотите глубже разобраться в функциональном программировании и писать более качественный код на Scala? Приходите на вебинар в
Хотите глубже разобраться в функциональном программировании и писать более качественный код на Scala? Приходите на вебинар в Otus 24 апреля в 20:00 пройдёт открытый вебинар с Алексеем Воронцом — руководителем разработки в Naumen, 14 лет опыта, из них 9 лет на Scala. На практических примерах он покажет: — почему Scala — функциональный язык — как работать с ключевыми библиотеками — как повысить выразительность кода ❗️ Если вы уже знакомы со Scala или только начинаете к нему присматриваться и хотите развивать функциональный подход в своих проектах — этот вебинар для вас. Каждый участник: — сможет задать вопросы эксперту — получит скидку на полный курс по Scala-разработке 👉 Регистрируйтесь и сделайте свой код лучше Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

🧠 Простое ускорение @Transactional методов в Spring Boot Знаете, что @Transactional по умолчанию оборачивает метод в прокси?
🧠 Простое ускорение @Transactional методов в Spring Boot Знаете, что @Transactional по умолчанию оборачивает метод в прокси? Это значит: - Внутренние вызовы в том же классе не проходят через транзакцию; - Каждый такой прокси — это AOP-магия, которую можно обойти ради производительности. 📌 Если вы точно знаете, что метод будет вызываться только извне, и вам не нужна прокси-обёртка — используйте @Transactional на уровне интерфейса и включите interface-based proxy.

@Configuration
@EnableTransactionManagement(proxyTargetClass = false) // JDK proxy
public class TransactionConfig {
}

public interface UserService {
    @Transactional
    void createUser(User user);
}
📉 Это немного снижает overhead, особенно в высоконагруженных сервисах, где сотни тысяч вызовов @Transactional-методов. 💡 Подходит, если: - У вас слоистая архитектура; - Транзакции нужны только снаружи; - Вы не используете вызовы this.someMethod() внутри сервиса. ⚠️ Не забывайте: - JDK Proxy работает только с интерфейсами; - Если вызываете методы внутри того же класса — прокси не сработает (и транзакция не начнётся). 📊 Профильте. Иногда замена proxyTargetClass = true на false даёт +3-5% к throughput. 👉@BookJava

🧠 Как ускорить загрузку контекста Spring Boot — простой приём Если у вас тяжёлый Spring Boot-приложение с кучей конфигураций
🧠 Как ускорить загрузку контекста Spring Boot — простой приём Если у вас тяжёлый Spring Boot-приложение с кучей конфигураций и бинов, время старта может легко вырасти до 20–30 секунд и больше. Сегодня покажу приём, который помогает ускорить cold start за счёт отключения ненужных автоматических конфигураций. 📌 Spring Boot автоконфигурация — это палка о двух концах. Она упрощает старт, но часто тянет за собой кучу лишнего. Особенно если вы используете @SpringBootApplication, которая включает в себя @EnableAutoConfiguration. 💡 Решение — использовать spring.autoconfigure.exclude, чтобы явно выключить ненужное. Например:

# application.yaml
spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
❗️Это особенно актуально: - в микросервисах без UI (отключаем MVC) - если datasource создаётся вручную - в тестах и lightweight-режимах 👀 Как понять, что мешает? 1. Запусти приложение с флагом --debug или логгером org.springframework.boot.autoconfigure уровня DEBUG. 2. Посмотри, какие автоконфигурации "matched", но тебе не нужны. 3. Добавь их в exclude. 🧰 Альтернатива — использовать аннотацию @ImportAutoConfiguration с явным списком нужных автоконфигураций. Это тонкая настройка, идеально для библиотек и SDK. ⚠️ Не переусердствуй: отключение нужной конфигурации может привести к тихим багам. Лучше вырезать по одной и смотреть на эффект. 👉 Это один из способов сделать Spring Boot предсказуемым и быстрым, особенно в CI/CD или serverless-окружениях. 👉@BookJava

👩‍💻 JDBC — ваш швейцарский нож для работы с данными Приглашаем на открытый урок. 🗓 22 апреля в 20:00 МСК 🆓 Бесплатно. Уро
👩‍💻 JDBC — ваш швейцарский нож для работы с данными Приглашаем на открытый урок. 🗓 22 апреля в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Professional». О чём поговорим: ✔️Основы JDBC: что это такое, зачем нужно и как работает ✔️Практические примеры выполнения сложных запросов ✔️Работа с транзакциями и обработка ошибок в JDBC ✔️ Оптимизация производительности при работе с данными через JDBC Кому будет интересно: Вебинар будет полезен разработчикам, инженерам по базам данных и архитекторам ПО, стремящимся улучшить навыки работы с базами данных и оптимизировать взаимодействие с данными. В результате урока: Вы научитесь эффективно использовать JDBC для работы с базами данных и сможете применять полученные знания в реальных проектах 🔗 Ссылка на регистрацию: https://vk.cc/cKRDCS Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

💡 Ленивая инициализация бинов в Spring Boot — мощный инструмент ускорения старта По умолчанию Spring инициализирует все singleton-бины при запуске приложения. Это может быть проблемой в больших проектах: старт медленный, а половина бинов не нужна сразу. 📌 Как ускорить старт и снизить потребление памяти? — Lazy Init! ✅ Глобально:

spring:
  main:
    lazy-initialization: true
Все бины станут ленивыми — создадутся только при первом обращении. Это может сократить старт приложения на 30-60%! ✅ Локально (избирательно):

@Component
@Lazy
public class HeavyBean {
    public HeavyBean() {
        System.out.println("HeavyBean init...");
    }
}
Или через @Lazy на зависимостях:

@Service
public class MyService {
    public MyService(@Lazy HeavyBean heavyBean) {
        this.heavyBean = heavyBean;
    }
}
🧠 Когда использовать: - В dev-окружении — чтобы ускорить локальный dev cycle. - В CLI/Batch-приложениях, где используется 1-2 бина. - Когда есть тяжёлые бины, не нужные на старте (например, интеграции, большие клиенты и т.п.). ⚠️ Осторожно: - Если забыть @Lazy на зависимостях, Spring всё равно создаст бин. - Некоторые бины должны быть загружены сразу (например, @Scheduled, @EventListener), иначе они не сработают. 👉@BookJava

❓Сталкиваетесь с задачами, когда вам нужно выбрать лучший алгоритм, но не понимаете, как анализировать их сложность? Ваш код
❓Сталкиваетесь с задачами, когда вам нужно выбрать лучший алгоритм, но не понимаете, как анализировать их сложность? Ваш код может быть медленным или неэффективным, и вы не знаете, как это исправить? 📗На открытом вебинаре 21 апреля в 20:00 мск вы освоите важные инструменты для анализа сложности алгоритмов, улучшите свой навык решения алгоритмических задач и на примере простых алгоритмов сортировки и увидите разницу при применении алгоритмов разной степени сложности. ➡️Регистрируйтесь прямо сейчас и получите скидку на большое обучение «C# Developer» по промокоду SHARP_SPEC_4: https://vk.cc/cKRCrB Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🧠 ThreadLocal — скрытая угроза утечек памяти ThreadLocal — удобный способ хранить данные, привязанные к потоку. Например, дл
🧠 ThreadLocal — скрытая угроза утечек памяти ThreadLocal — удобный способ хранить данные, привязанные к потоку. Например, для SimpleDateFormat или текущего пользователя в рамках запроса. Но с ним легко получить утечку памяти, особенно в thread pool'ах. 📌 Почему? ThreadLocal-хранилище (Thread.threadLocals) живёт столько же, сколько поток. А потоки из пулов живут долго. Если ты забыл вызвать remove() — данные останутся в памяти навсегда. Пример:

private static final ThreadLocal<UserContext> context = ThreadLocal.withInitial(UserContext::new);

public void handleRequest() {
    try {
        context.set(new UserContext("user123"));
        // работа с контекстом
    } finally {
        context.remove(); // ОБЯЗАТЕЛЬНО!
    }
}
⚠️ Что пойдёт не так без remove()? - Поток из пула закончит обрабатывать запрос, но UserContext останется висеть в ThreadLocalMap этого потока. - Если UserContext содержит ссылки на другие объекты (например, HttpSession, EntityManager и т.д.) — вся эта цепочка не будет GC-шиться. - И так накапливается утечка. 💡 Советы: - Всегда вызывай remove() в finally. - Для Spring можно использовать RequestScope или @ControllerAdvice вместо ThreadLocal. - Проверяй код сторонних библиотек, если они используют ThreadLocal, особенно в фильтрах и интерсепторах. 👉@BookJava