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

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

الذهاب إلى القناة على Telegram

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

إظهار المزيد

📈 نظرة تحليلية على قناة تيليجرام Библиотека Java разработчика

تُعد قناة Библиотека Java разработчика (@bookjava) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 10 121 مشتركاً، محتلاً المرتبة 11 760 في فئة التكنولوجيات والتطبيقات والمرتبة 63 248 في منطقة روسيا.

📊 مؤشرات الجمهور والحراك

منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 10 121 مشتركاً.

بحسب آخر البيانات بتاريخ 25 أغسطس, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -74، وفي آخر 24 ساعة بمقدار -6، مع بقاء الوصول العام مرتفعاً.

  • حالة التحقق: غير موثّقة
  • معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 7.20‎%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 3.71‎% من ردود الفعل نسبةً إلى إجمالي المشتركين.
  • وصول المنشورات: يحصل كل منشور على متوسط 729 مشاهدة. وخلال اليوم الأول يجمع عادةً 376 مشاهدة.
  • التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 5.
  • الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل string, интерфейс, строка, boot, api.

📝 الوصف وسياسة المحتوى

يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP

بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 26 أغسطس, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.

10 121
المشتركون
-624 ساعات
-137 أيام
-7430 أيام
أرشيف المشاركات
🧠 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() уже безопасно очищает контекст. 💡 Эта ошибка особенно коварна, потому что не всегда проявляется — зависит от настроек, триггеров в БД, кэша и т.д. 📲 Мы в MAX 👉@BookJava

🚀 Подборка полезных 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 Типичный Сисадмин https://max.ru/channel_win_sysadmin Системный Администратор Windows https://max.ru/channel_linux_admin Linux: Системный администратор https://max.ru/channel_linuxmod Linux https://max.ru/channel_i_linux Системный администратор https://max.ru/channel_devopslib DevOps, SRE, Sysadmin https://max.ru/channel_devops_star DevOps Star (Звезда Девопса) Excel лайфхак 📌 https://t.me/Excel_lifehack Excel лайфхак Английский с нуля 🇬🇧 https://max.ru/UchuEnglish 1C разработка 📌 https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С https://max.ru/channel_DevLab1C 1С:Предприятие 8 Программирование C++📌 https://max.ru/cpp_lib Библиотека C/C++ разработчика https://max.ru/channel_cpp_geek C++ geek Программирование Go📌 https://max.ru/golang_lib Библиотека Go (Golang) разработчика Программирование React📌 https://max.ru/react_lib React Программирование Rust📌 https://max.ru/channel_rust_lib Программирование Python 📌 https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчика Java разработка 📌 https://max.ru/bookjava Библиотека Java разработчика https://max.ru/channel_java_geek Java Geek 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 Обучающие видео, книги по Физике и Математике Вакансии в IT📌 https://max.ru/progjob https://max.ru/channel_rabotait Мир технологий 📌 https://max.ru/mir_teh Канал для любознательных Бонус 📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга https://max.ru/mockva_life Свежие новости Москвы https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП

🧠 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 могут открыть глаза. 📲 Мы в MAX 👉@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>. - Это особенно критично для тестов, лямбд и кэширования. 📲 Мы в MAX 👉@BookJava

🧠 Сейчас покажу баг, который легко пропустить при работе с @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-методы живут в отдельных сервисах, их проще тестировать и не возникает подобных ловушек. 📲 Мы в MAX 👉@BookJava

🇷🇺 Разбираешься в радиочипах, оптике и связи? Забери до 1 000 000 рублей за свои инженерные навыки на турнире «Дронкон» 🇷�
🇷🇺 Разбираешься в радиочипах, оптике и связи? Забери до 1 000 000 рублей за свои инженерные навыки на турнире «Дронкон» 🇷🇺 «Сталинские Соколы» открывают регистрацию на 4-й Всероссийский турнир «Дронкон», который пройдет с 22 по 26 августа. Турнир пройдет по направлению: - Инженерное дело: навыки программирования, сборка электронного оборудования, беспроводная связь, оптические системы + стратегия «Битва Дронов»; Призовой фонд для победителей:
🥇место – 1 000 000 рублей 🥈место – 700 000 рублей 🥉место – 500 000 рублей Награда за 4-8 места - 100 000 рублей
Пройди заочный онлайн-этап и получи путевку на очный этап турнира в Республику Татарстан! Перелет, питание, проживание - за счет организаторов. 🇷🇺 Подать заявку и узнать подробности 🇷🇺

🧠 Простое ускорение @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. 📲 Мы в MAX 👉@BookJava

👩‍💻 Основы многопоточности в Java Приглашаем на открытый урок. 🗓 23 июля в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта ку
👩‍💻 Основы многопоточности в Java Приглашаем на открытый урок. 🗓 23 июля в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Java-разработчик». На уроке разберем: ✔️ Что такое поток выполнения и почему даже обычная Java-программа работает в главном потоке main. ✔️ Как создавать и запускать потоки через Thread и Runnable. ✔️ Зачем нужен join и как дождаться завершения запущенных потоков. ✔️ Почему многопоточность может ускорить программу, а может добавить лишние накладные расходы. ✔️ Какие типовые проблемы возникают в многопоточном коде: гонки, starvation и deadlock. 🔗 Ссылка на регистрацию: https://vk.cc/cZD2sI Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🧠 Как ускорить загрузку контекста 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-окружениях. 📲 Мы в MAX 👉@BookJava

💡 Ленивая инициализация бинов в 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), иначе они не сработают. 📲 Мы в MAX 👉@BookJava

👩‍💻 DAO на Spring JDBC Приглашаем на открытый урок. 🗓 22 июля в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Разраб
👩‍💻 DAO на Spring JDBC Приглашаем на открытый урок. 🗓 22 июля в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Разработчик на Spring Framework». На занятии мы разберем: ✔️Преимущества нативного SQL при разработке DAO. ✔️ Основные возможности Spring JDBC для работы с запросами. ✔️ Подходы к обеспечению безопасности и тестируемости DAO. Кому будет интересно: Урок будет полезен Java-разработчикам, архитекторам ПО и специалистам по базам данных, стремящимся оптимизировать доступ к данным. 🔗 Ссылка на регистрацию: https://vk.cc/cZxief Реклама. ООО «Отус онлайн-образование», ОГРН 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, особенно в фильтрах и интерсепторах. 📲 Мы в MAX 👉@BookJava

🧠 Как ускорить cold start Spring Boot приложения Как можно сократить время старта Spring Boot 3+ приложения — без GraalVM и
🧠 Как ускорить cold start Spring Boot приложения Как можно сократить время старта Spring Boot 3+ приложения — без GraalVM и без магии. 📌 Используем флаг:

-Dspring.context.cache.applicationContext=true
💡 Что это такое? Это встроенный механизм кэширования ApplicationContext, появившийся в Spring Boot 3.2. Он сохраняет результат построения контекста и позволяет повторно использовать его между запусками, особенно в тестах и development-сценариях. ⚙️ Как работает: - При первом запуске контекст билдится как обычно. - Затем сериализуется и сохраняется на диск. - При следующем запуске он подгружается из кеша (если не изменился), что даёт ускорение в 2-3 раза и больше. 🚀 Отлично подходит для: - Тестов (@SpringBootTest); - Dev tools и локального запуска; - Разработки больших монолитов. ⚠️ Не влияет на продакшн (там кеш не используется по умолчанию) ⚠️ Не поддерживает все конфигурации (например, динамические настройки могут инвалидировать кеш) Простой флаг — а экономит кучу времени каждый день. 📲 Мы в MAX 👉@BookJava

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

@Service
public class UserService {

    @Transactional
    public void registerUser(UserDto dto) {
        saveUser(dto);
    }

    @Transactional
    public void saveUser(UserDto dto) {
        // сохранение пользователя
    }
}
💥 Проблема: Spring не применит транзакцию к saveUser(), потому что вызов происходит внутри одного и того же бина — минуя прокси. Spring AOP работает через прокси, и @Transactional "срабатывает", только если метод вызывается извне, через прокси-объект. ⚠️ Это может привести к очень странным багам: вы думаете, что транзакция есть, а её нет. 💡 Как исправить: 1. Вынести метод в отдельный бин:

@Service
public class UserSaver {
    @Transactional
    public void save(UserDto dto) {
        // сохраняем
    }
}

@Service
public class UserService {
    private final UserSaver saver;

    public UserService(UserSaver saver) {
        this.saver = saver;
    }

    public void registerUser(UserDto dto) {
        saver.save(dto);
    }
}
2. Или использовать TransactionTemplate вручную. ✅ Всегда проверяйте, как вызываются методы с @Transactional. Особенно при рефакторинге! 📲 Мы в MAX 👉@BookJava

👩‍💻 Стоит ли учить Java в 2026: куда движется язык и где работают джависты Приглашаем на открытый урок. 🗓 16 июля в 20:00
👩‍💻 Стоит ли учить Java в 2026: куда движется язык и где работают джависты Приглашаем на открытый урок. 🗓 16 июля в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Java-разработчик». Программа урока: ✔️ Развенчиваем главный миф новичка: правда ли, что «Java умерла» и всем надо идти в Python или Go ✔️ Где Java реально работает в 2026: банки, финтех, маркетплейсы, стриминги с миллионами пользователей, логистика ✔️ Big Data на JVM: почему Kafka, Spark и Hadoop написаны на Java и зачем это знать даже питонисту ✔️ Куда движется язык: релизы каждые полгода, борьба с многословностью, нативная компиляция (GraalVM), связка с AI ✔️ Карьера джависта: зарплаты, стабильность и почему этот язык — фундамент для долгого пути в IT 🔗 Ссылка на регистрацию: https://vk.cc/cZloUh Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🧠 @Value vs @ConfigurationProperties — кого выбрать? Часто вижу, как даже опытные разработчики по привычке используют @Value для инъекции конфигурации:

@Value("${app.timeout}")
private Duration timeout;
⚠️ Но с ростом приложения @Value становится хрупким и неудобным. 📌 Лучший подход — использовать @ConfigurationProperties:

@ConfigurationProperties(prefix = "app")
public record AppProperties(Duration timeout, String apiKey) {}

@Bean
@ConfigurationPropertiesBinding
public AppProperties appProperties() {
    return new AppProperties();
}
✅ Преимущества @ConfigurationProperties: - 💡 Группирует настройки логически - 🔍 Работает с валидацией (@Validated, @NotNull, и т.д.) - 📚 Отлично поддерживается IDE (автокомплит, рефакторинг) - 🔧 Удобно тестировать и мокать 🆕 Начиная с Spring Boot 2.2+, можно использовать record-классы и просто зарегистрировать бин через @EnableConfigurationProperties:

@Configuration
@EnableConfigurationProperties(AppProperties.class)
public class AppConfig {}
Так что, если у вас в проекте до сих пор десятки @Value — самое время навести порядок. 📲 Мы в MAX 👉@BookJava

🧠 @Value в Spring — это ловушка, если вы используете списки или map'ы Многие знают, что можно заинжектить список строк из application.yml вот так:

app:
  langs:
    - en
    - fr
    - de

@Value("${app.langs}")
private List<String> langs;
Но знаете, что вы получите? ⚠️ ОШИБКУ. @Value не умеет парсить YAML-массивы. Он ожидает строку, и даже с CSV-строкой (en,fr,de) — всё не так очевидно: Spring не применяет ConversionService для списков. 📌 Решение — использовать @ConfigurationProperties:

app:
  langs:
    - en
    - fr
    - de

@ConfigurationProperties(prefix = "app")
@Component
public class AppProps {
    private List<String> langs;
    // геттеры/сеттеры
}
💡 Профит: - работает с List, Map, вложенными объектами; - валидация через @Validated и @NotEmpty; - легко покрыть тестами; - меньше магии. ⚠️ @Value хорош для простых скаляров. Всё остальное — через @ConfigurationProperties. 📲 Мы в MAX 👉@BookJava

🔍 Почему Optional — это не замена null везде и всегда Привет! Сегодня хочу поделиться одной из часто встречающихся ошибок при использовании Optional в Java. Многие разработчики, особенно начинающие, начинают использовать Optional везде, где может быть null, думая, что это автоматически делает код "безопасным". Но так ли это? 📌 Ключевая идея Optionalсигнализировать о возможном отсутствии значения в результате вызова метода. А не заменять все поля и параметры на Optional. Примеры плохой практики:

public class User {
    private Optional<String> name; // ❌ Не нужно так делать
}
Почему это плохо: - Увеличивается сложность сериализации (особенно с Jackson, GSON). - Не соответствует архитектурной задумке: Optional — это не контейнер для полей. - Проблемы с JPA (Hibernate не дружит с Optional-полями). - Понижается читаемость кода. 💡 Лучше использовать Optional вот так:

public Optional<User> findUserById(Long id) {
    // Возвращаем Optional, потому что пользователь может не существовать
}
То есть Optional — это про контракт на метод, а не про хранение данных. Если кратко: - ✅ Используй Optional в сигнатурах методов, когда результат может отсутствовать. - ❌ Не используй Optional в полях и параметрах конструктора. А ты как используешь Optional в проектах? Был ли опыт с его неправильным применением? Пиши в комментах👇 📲 Мы в MAX 👉@BookJava

👩‍💻 Как работает @Transactional в Spring: границы транзакций и типовые ошибки Приглашаем на открытый урок. 🗓 29 июня в 20:
👩‍💻 Как работает @Transactional в Spring: границы транзакций и типовые ошибки Приглашаем на открытый урок. 🗓 29 июня в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Разработчик на Spring Framework». На занятии мы разберем: ✔️Что реально делает @Transactional в Spring ✔️Почему важны proxy и вызов метода через Spring Bean ✔️Как работают propagation-режимы на примере REQUIRED и REQUIRES_NEW ✔️Когда происходит rollback и почему checked exceptions не всегда откатывают транзакцию ✔️Типовые ошибки при работе с транзакциями в сервисном слое Урок будет полезен Java/Kotlin-разработчикам, которые уже пишут приложения на Spring или начинают использовать Spring в реальных backend-проектах и хотят лучше понимать поведение транзакций. 🔗 Ссылка на регистрацию: https://vk.cc/cZ9GGY Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🧠 Как Java хранит boolean в памяти? Сегодня я покажу вам, почему boolean в Java — это не просто true или false. А за этим простым типом скрывается интересный нюанс, особенно если ты задумываешься об экономии памяти. В Java нет отдельного типа, который занимает всего 1 бит. Хотя логично было бы ожидать, что boolean — это один бит (true/false), на самом деле в памяти он занимает 1 байт (а иногда и больше, в зависимости от структуры объекта). Пример:

public class Flags {
    boolean flag1;
    boolean flag2;
    boolean flag3;
}
Ты думаешь — три бита. Но JVM выравнивает поля, и из-за этого объект может занимать 16 байт или больше, в зависимости от архитектуры. Почему так? 📌 Причина: JVM упрощает модель памяти ради производительности — доступ к байтам быстрее, чем к битам. Нет битовых сдвигов, масок и лишней логики. 💡 Что делать, если хочется сэкономить память? Используй BitSet:

BitSet flags = new BitSet(3);
flags.set(0, true);
Это уже реальная битовая структура. Отличный выбор, если у тебя десятки или сотни логических флагов. А ты знал об этом нюансе хранения boolean? Пиши в комментариях, сталкивался ли с перерасходом памяти из-за простых типов. 📲 Мы в MAX 👉@BookJava