Можно ли использовать аннотацию @Profile для создания бина только при локальном запуске
Что проверяют
Знаете ли вы механизм профилей Spring и, главное, как сделать так, чтобы локальный бин гарантированно не попал на прод. Следом спрашивают, как именно активируется профиль и чем @Profile отличается от @ConditionalOnProperty.
Как отвечать
Да, это прямое назначение @Profile. Аннотация ставится на класс с @Component, на метод @Bean или на целый @Configuration, и бин регистрируется, только если профиль активен:
@Bean @Profile("local") MailSender fakeMailSender() { return new LoggingMailSender(); }
Дальше важно, как активировать профиль, не задев остальные окружения:
- переменная окружения:
SPRING_PROFILES_ACTIVE=localили-Dspring.profiles.active=localв run-конфигурации IDE; - сборка:
./mvnw spring-boot:run -Dspring-boot.run.profiles=local, для Gradle./gradlew bootRun --args='--spring.profiles.active=local'; - конфиг: локальные настройки лежат в
application-local.yml, он подхватывается автоматически при активном профиле.
Выражения в @Profile поддерживают логику: "!prod", "local & !docker", "local | dev". Если ни один профиль не задан, активен профиль default.
Для пары «заглушка локально, настоящий клиент везде» объявляют два бина одного типа с @Profile("local") и @Profile("!local"), чтобы в любом окружении был ровно один. Альтернатива: @ConditionalOnProperty удобнее, когда фича включается флагом в конфиге, а не окружением целиком. А для локальной базы в Spring Boot сейчас чаще берут поддержку Docker Compose или Testcontainers, чем отдельный профиль с ручными настройками.
Где спотыкаются
Пишут spring.profiles.active=local в общий application.properties, который коммитится. Если на проде переменная окружения не задана, локальные заглушки уезжают туда же.
Используют @Profile("!prod") для локального бина. Любое окружение, где забыли выставить prod, получит заглушку, поэтому надёжнее явное включение через local.
Забывают про зависимых. Если другой бин требует локальный бин, а в проде его нет, приложение упадёт на старте с NoSuchBeanDefinitionException. В тестах профиль задают через @ActiveProfiles("local"), а не через системные свойства.