🧠 Простое ускорение
Знаете, что
Это значит:
- Внутренние вызовы в том же классе не проходят через транзакцию;
- Каждый такой прокси — это AOP-магия, которую можно обойти ради производительности.
📌 Если вы точно знаете, что метод будет вызываться только извне, и вам не нужна прокси-обёртка — используйте
📉 Это немного снижает overhead, особенно в высоконагруженных сервисах, где сотни тысяч вызовов
💡 Подходит, если:
- У вас слоистая архитектура;
- Транзакции нужны только снаружи;
- Вы не используете вызовы
⚠️ Не забывайте:
- JDK Proxy работает только с интерфейсами;
- Если вызываете методы внутри того же класса — прокси не сработает (и транзакция не начнётся).
📊 Профильте. Иногда замена
👉@BookJava
@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
👍7
Хотите глубже разобраться в функциональном программировании и писать более качественный код на Scala? Приходите на вебинар в Otus
24 апреля в 20:00 пройдёт открытый вебинар с Алексеем Воронцом — руководителем разработки в Naumen, 14 лет опыта, из них 9 лет на Scala. На практических примерах он покажет:
— почему Scala — функциональный язык
— как работать с ключевыми библиотеками
— как повысить выразительность кода
❗️ Если вы уже знакомы со Scala или только начинаете к нему присматриваться и хотите развивать функциональный подход в своих проектах — этот вебинар для вас.
Каждый участник:
— сможет задать вопросы эксперту
— получит скидку на полный курс по Scala-разработке
👉 Регистрируйтесь и сделайте свой код лучше
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
24 апреля в 20:00 пройдёт открытый вебинар с Алексеем Воронцом — руководителем разработки в Naumen, 14 лет опыта, из них 9 лет на Scala. На практических примерах он покажет:
— почему Scala — функциональный язык
— как работать с ключевыми библиотеками
— как повысить выразительность кода
❗️ Если вы уже знакомы со Scala или только начинаете к нему присматриваться и хотите развивать функциональный подход в своих проектах — этот вебинар для вас.
Каждый участник:
— сможет задать вопросы эксперту
— получит скидку на полный курс по Scala-разработке
👉 Регистрируйтесь и сделайте свой код лучше
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👍2👎1
🧠 Сейчас покажу баг, который легко пропустить при работе с
📌 Проблема — транзакция не работает, потому что метод вызывается изнутри того же класса.
Рассмотрим пример:
💥 Если
✅ Решения:
1. Вынести transactional-метод в отдельный бин:
2. Внедрить self-прокси:
3. Использовать
⚠️ Не забудь включить
💡 Современный подход — разделение ответственности: transactional-методы живут в отдельных сервисах, их проще тестировать и не возникает подобных ловушек.
👉@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-методы живут в отдельных сервисах, их проще тестировать и не возникает подобных ловушек.
👉@BookJava
👍7❤1
🧠 Lazy Initialization по-взрослому: не создавай проблемы на ровном месте
В Spring Boot часто можно встретить вот такую конструкцию:
⚠️ Проблема:
📌 Решение — ленивая инициализация, но не через старый добрый
💡 Способ #1:
Можно и без Guava:
💡 Способ #2: через Spring
🧵 Итог:
- Не инициализируй тяжёлые объекты зря.
- Используй
- Это особенно критично для тестов, лямбд и кэширования.
👉@BookJava
В 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
👍9
🧠 Spring Boot 3.2+: ускоряем стартап с помощью
Spring Boot 3.2 по умолчанию включает сбор Micrometer Observation метрик — даже если вы не используете Prometheus, Datadog и пр.
Это полезно, но часто избыточно — особенно в микросервисах, где важна скорость старта.
📌 Что это даёт?
- Отключает автоконфигурацию
- Убирает связанные
- Сокращает время старта до 30-60% (в зависимости от контекста)
💡 Как применить?
В
Или так, если используешь
⚠️ Важно: это не отключает другие метрики Micrometer.
Это касается только новой подсистемы Observation — она полезна для трассировки, но не всегда нужна.
📎 Документация Micrometer Observation
👉@BookJava
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
👍3
23 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
📂 Илья Аров, старший разработчик в Т1, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Илья будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Илье
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzqvv6bu4
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzqvv6bu4
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🧠 Spring Boot и медленные autowire — проверь, не зарыта ли у тебя бомба в
Есть распространённый анти-паттерн: ты используешь
⚠️ Проблема: такие методы вызываются при старте контекста, и если
📌 Хуже всего, если ты не подозреваешь об этом: ведь
💡 Совет:
- Используй
- Разделяй конфигурацию: отдельно core, отдельно init-heavy.
- Не бойся отказаться от
И главное — профилируй старт.
👉@BookJava
@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
👍5
Осталось всего 2 дня — углубитесь в функциональное программирование на Scala в Otus 📢
24 апреля в 20:00 пройдёт открытый вебинар с Алексеем Воронцом — руководителем разработки в Naumen, 14 лет опыта, из них 9 лет на Scala. Он расскажет:
— почему Scala — функциональный язык
— как работать с ключевыми библиотеками
— как повысить выразительность кода
Если вы уже знакомы со Scala или желаете перейти на него и хотите развивать функциональный подход в своих проектах — этот вебинар для вас.
Каждый участник:
— сможет задать вопросы эксперту
— получит скидку на полный курс по Scala-разработке
👉 Не упустите возможность перейти на новый уровень — регистрируйтесь, осталось 2 дня до начала
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
24 апреля в 20:00 пройдёт открытый вебинар с Алексеем Воронцом — руководителем разработки в Naumen, 14 лет опыта, из них 9 лет на Scala. Он расскажет:
— почему Scala — функциональный язык
— как работать с ключевыми библиотеками
— как повысить выразительность кода
Если вы уже знакомы со Scala или желаете перейти на него и хотите развивать функциональный подход в своих проектах — этот вебинар для вас.
Каждый участник:
— сможет задать вопросы эксперту
— получит скидку на полный курс по Scala-разработке
👉 Не упустите возможность перейти на новый уровень — регистрируйтесь, осталось 2 дня до начала
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
🧠 JPA: не забывай про
Если ты используешь EntityManager вручную, например, при батчевой вставке или обновлении, то, скорее всего, пишешь что-то вроде:
⚠️ Но тут баг: без
✅ Правильно так:
📌
💡 Эта ошибка особенно коварна, потому что не всегда проявляется — зависит от настроек, триггеров в БД, кэша и т.д.
👉@BookJava
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
👍9
Чем отличаются checked и unchecked исключения в java?
В Java исключения делятся на два основных типа: checked и unchecked. Разница между ними ключевая и касается как обработки, так и структуры кода.
✅ Checked Exceptions (Проверяемые исключения)
Примеры:
Отличия:
1. Проверяются компилятором — вы обязаны либо обработать их с помощью
2. Производные от
3. Используются для ситуаций, которые можно разумно ожидать и обработать (например, отсутствие файла, проблемы с сетью).
Пример:
❌ Unchecked Exceptions (Непроверяемые исключения)
Примеры:
Отличия:
1. Не проверяются компилятором — вы не обязаны их обрабатывать или декларировать.
2. Производные от
3. Возникают в результате ошибок в логике программы или непредвиденных ситуаций.
Пример:
Если кратко:
Checked — ошибки среды, требующие явной обработки.
Unchecked — ошибки в логике, ответственность программиста.
👉@BookJava
В 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
👍7
Курс «Java Developer. Professional» — это структурированное обучение для разработчиков, которые хотят выйти на новый уровень, освоить актуальный стек технологий и уверенно претендовать на позиции уровня Middle+.
Программа OTUS постоянно обновляется, соответствуя требованиям рынка, а диплом ценится работодателями.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🤬1💩1
🧠 Как избежать N+1 при использовании
Одна из самых коварных ловушек JPA - это N+1 проблема. Особенно часто она проявляется при
Вы загружаете список авторов, а потом проходите по каждому и вызываете
📌 Решение -
Оба варианта решают проблему, но
⚡️ Или через JPQL:
💡 Совет: всегда думайте о графе объектов. Если вам нужно сразу подтянуть связанные сущности — делайте это явно. Не надейтесь на LAZY по умолчанию.
⚠️ Осторожно с пагинацией и JOIN FETCH — могут появиться дубликаты или проблемы с
👉@BookJava
@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
👍5
🧠 JPA: подводный камень с
Сегодня покажу, почему
📌 Суть проблемы
При использовании
Запрос
1 запрос на
💡 Почему это больно
Даже если вы используете
⚠️ Особенно опасно при pagination
Если вы делаете
✅ Что делать
1. Делайте
2. Если нужно подгрузить коллекцию — используйте
Или вручную:
👉 Следи за
👉@BookJava
@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
👍6
На открытом уроке «Облако в кармане: запускаем всю инфраструктуру для теста при сборке» от OTUS мы расскажем, как избежать ручных настроек и запусков. Вместо этого вы научитесь автоматизировать весь процесс с помощью Docker, DockerCompose и TestContainers, интегрируя их с Gradle.
Урок полезен для разработчиков на Kotlin и Java, которые работают с автотестами — интеграционными и end-to-end.
В ходе урока вы освоите:
▫️Автоматический запуск всей необходимой инфраструктуры для тестирования.
▫️Создание Docker-образов для тестов и деплоя.
▫️Разработку автотестов, которые поднимут ваши навыки на новый уровень.
Участники получат скидку на курс «Kotlin Backend Developer. Professional».
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
Сегодня покажу вам 🧠 один тонкий момент в работе с
Многие пишут так:
⚠️ Это антипаттерн! Вы теряете суть
📌 Правильный способ — использовать функциональный стиль:
Или ещё элегантнее:
💡 Подходы:
-
-
-
-
📈 Выгоды:
- Код становится компактнее
- Безопаснее при рефакторинге
- Лучше для чтения в потоковых операциях (
🛠 Если нужно вынуть значение — используйте
👉 Отказывайтесь от
👉@BookJava
Optional
, который часто ловит даже опытных.Многие пишут так:
Optional<String> optional = getValue();
if (optional.isPresent()) {
doSomething(optional.get());
}
⚠️ Это антипаттерн! Вы теряете суть
Optional
и рискуете ошибками в многопоточке.📌 Правильный способ — использовать функциональный стиль:
getValue().ifPresent(this::doSomething);
Или ещё элегантнее:
getValue()
.map(this::transform)
.filter(this::isValid)
.ifPresent(this::doSomething);
💡 Подходы:
-
map
для преобразования значения-
filter
для отсеивания ненужных-
orElse
, orElseGet
, orElseThrow
для обработки отсутствия-
ifPresentOrElse
в Java 9+ для двух вариантов действий📈 Выгоды:
- Код становится компактнее
- Безопаснее при рефакторинге
- Лучше для чтения в потоковых операциях (
Stream API
)🛠 Если нужно вынуть значение — используйте
orElseThrow()
вместо .get()
:
String value = getValue().orElseThrow(() -> new IllegalStateException("Value not found"));
👉 Отказывайтесь от
.isPresent()
и .get()
связки — используйте силу функционального подхода! 🚀👉@BookJava
👍7👎5
🚀 Подборка Telegram каналов для программистов
Системное администрирование, DevOps 📌
https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Системное администрирование, DevOps 📌
https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Telegram
Bash Советы
🚀 Секреты и советы по Bash
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
🔥1
📌 Ошибка: Вызов метода с
Почему? Spring оборачивает бин в прокси, а внутренние вызовы проходят мимо прокси, значит, аннотация игнорируется.
Пример проблемы:
💡 Как правильно:
1. Вынести
2. Или получить прокси текущего бина через
⚠️ Важный момент:
Понимание этой тонкости критично для корректного управления транзакциями в Spring! 🚀
👉@BookJava
@Transactional
внутри того же класса не запускает новую транзакцию.Почему? Spring оборачивает бин в прокси, а внутренние вызовы проходят мимо прокси, значит, аннотация игнорируется.
Пример проблемы:
@Service
public class OrderService {
@Transactional
public void createOrder() {
saveOrder();
}
@Transactional
public void saveOrder() {
// Новый транзакционный контекст не создастся!
}
}
💡 Как правильно:
1. Вынести
saveOrder()
в отдельный бин.2. Или получить прокси текущего бина через
AopContext
:
@Service
@EnableAspectJAutoProxy(exposeProxy = true) // важно!
public class OrderService {
@Transactional
public void createOrder() {
((OrderService) AopContext.currentProxy()).saveOrder();
}
@Transactional
public void saveOrder() {
// Теперь всё ок ✅
}
}
⚠️ Важный момент:
exposeProxy = true
нужен на уровне конфигурации, иначе AopContext
не заработает.Понимание этой тонкости критично для корректного управления транзакциями в Spring! 🚀
👉@BookJava
👍5👎3
🧠 Сегодня покажу вам полезный трюк для Spring Boot: как элегантно валидировать параметры контроллера без лишнего кода.
Часто вижу, как в контроллерах вручную проверяют
Вместо этого используйте аннотации валидации прямо на параметрах:
📌 Ключевые моменты:
- Обязательно ставим
- На параметры добавляем любые стандартные аннотации из
- Ошибки валидации Spring обработает автоматически через
💡 Можно кастомизировать ответ на ошибку, добавив глобальный
⚠️ Без
👉@BookJava
Часто вижу, как в контроллерах вручную проверяют
@RequestParam
на пустоту или формат. Это шумит код и приводит к ошибкам.Вместо этого используйте аннотации валидации прямо на параметрах:
@RestController
@RequestMapping("/api")
@Validated // Обязательно!
public class UserController {
@GetMapping("/users")
public List<User> getUsers(
@RequestParam @NotBlank String name,
@RequestParam @Min(18) int age
) {
// Если валидация не пройдена — автоматически вернётся 400 Bad Request
return userService.findUsers(name, age);
}
}
📌 Ключевые моменты:
- Обязательно ставим
@Validated
над классом контроллера.- На параметры добавляем любые стандартные аннотации из
jakarta.validation.constraints
.- Ошибки валидации Spring обработает автоматически через
MethodArgumentNotValidException
.💡 Можно кастомизировать ответ на ошибку, добавив глобальный
@ExceptionHandler
.⚠️ Без
@Validated
аннотации на контроллере валидация параметров работать не будет!👉@BookJava
👍10
Есть фича. Есть дедлайн. Есть понимание, что тесты надо писать… но они отъедают время, которого итак впритык.
Один наш знакомый девелопер сказал: «С тех пор как поставил Explyt Test — начал писать меньше тестов… но покрытие стало лучше. Как это вообще возможно?!»
Попробуйте сами. Плагин сам предлагает тесты для вашего кода — прямо в IDE.
👉 explyt.ai — сэкономь себе пару часов уже сегодня.
Один наш знакомый девелопер сказал: «С тех пор как поставил Explyt Test — начал писать меньше тестов… но покрытие стало лучше. Как это вообще возможно?!»
Попробуйте сами. Плагин сам предлагает тесты для вашего кода — прямо в IDE.
👉 explyt.ai — сэкономь себе пару часов уже сегодня.
👍4🔥1
В Java instance initializer blocks (блоки инициализации экземпляра) выполняются в следующем порядке:
- Они выполняются каждый раз, когда создается новый объект класса.
- Выполнение происходит после вызова конструктора родительского класса (
Порядок инициализации:
1. Сначала инициализируются поля в порядке их объявления.
2. Затем выполняются instance initializer blocks, в том порядке, в котором они написаны в коде.
3. После этого выполняется тело конструктора.
Пример:
Вывод:
Ключевые моменты:
- Статические блоки (
- Instance initializer blocks полезны для общей инициализации, которую нужно выполнять вне зависимости от того, какой конструктор вызывается.
👉@BookJava
- Они выполняются каждый раз, когда создается новый объект класса.
- Выполнение происходит после вызова конструктора родительского класса (
super()
), но до тела конструктора текущего класса.Порядок инициализации:
1. Сначала инициализируются поля в порядке их объявления.
2. Затем выполняются instance initializer blocks, в том порядке, в котором они написаны в коде.
3. После этого выполняется тело конструктора.
Пример:
class Example {
int x = 10;
{
System.out.println("Instance initializer block");
x = 20;
}
Example() {
System.out.println("Constructor");
System.out.println("x = " + x);
}
public static void main(String[] args) {
Example ex = new Example();
}
}
Вывод:
Instance initializer block
Constructor
x = 20
Ключевые моменты:
- Статические блоки (
static {}
) — другое дело: они выполняются один раз при загрузке класса.- Instance initializer blocks полезны для общей инициализации, которую нужно выполнять вне зависимости от того, какой конструктор вызывается.
👉@BookJava
👍7🔥3
Как работают instance initializer blocks.
Пример с родительским и дочерним классами:
Вывод программы:
Пошаговое выполнение:
1. Сначала загружается родительский класс
2. Выполняется:
- Инициализация полей родителя (
- Потом instance initializer блока родителя (
- Потом конструктор родителя (
3. Далее переходим к дочернему классу
- Инициализация полей дочернего класса (
- Потом instance initializer блока дочернего класса (
- Потом конструктор дочернего класса (
Важный порядок действий:
1. Инициализация родителя → 2. Конструктор родителя → 3. Инициализация потомка → 4. Конструктор потомка.
Блоки инициализации всегда выполняются до тела конструктора, но после вызова
👉@BookJava
Пример с родительским и дочерним классами:
class Parent {
int a = 5;
{
System.out.println("Parent instance initializer");
a = 10;
}
Parent() {
System.out.println("Parent constructor, a = " + a);
}
}
class Child extends Parent {
int b = 15;
{
System.out.println("Child instance initializer");
b = 25;
}
Child() {
System.out.println("Child constructor, b = " + b);
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child();
}
}
Вывод программы:
Parent instance initializer
Parent constructor, a = 10
Child instance initializer
Child constructor, b = 25
Пошаговое выполнение:
1. Сначала загружается родительский класс
Parent
.2. Выполняется:
- Инициализация полей родителя (
a = 5
),- Потом instance initializer блока родителя (
a = 10
),- Потом конструктор родителя (
Parent()
).3. Далее переходим к дочернему классу
Child
:- Инициализация полей дочернего класса (
b = 15
),- Потом instance initializer блока дочернего класса (
b = 25
),- Потом конструктор дочернего класса (
Child()
).Важный порядок действий:
1. Инициализация родителя → 2. Конструктор родителя → 3. Инициализация потомка → 4. Конструктор потомка.
Блоки инициализации всегда выполняются до тела конструктора, но после вызова
super()
.👉@BookJava
👍6