Spring: вопросы с ответами

97 разобранных вопросов по теме «Spring». Каждый — с правильным ответом и пояснением.

  • 401 vs 403 — в чём разница?

    401 Unauthorized: не аутентифицирован (нет токена или токен невалидный). 403 Forbidden: аутентифицирован, но нет прав (пытаешься удалить чужой заказ). Ловушка: 401 — про identity, 403 — про permissions.

  • В чём разница: AOP: JDK proxy vs CGLIB?

    JDK dynamic proxy — если бин реализует интерфейс (через Proxy.newProxyInstance). CGLIB — наследование от класса (final-классы нельзя проксировать). Spring Boot 3 по умолчанию использует CGLIB.

  • AOP: кейс «замерить время всех методов сервиса»?

    @Aspect + @Around("execution(* com.example.service.*.*(..))"). ProceedingJoinPoint: long start = System.nanoTime(); Object result = pjp.proceed(); long elapsed = System.nanoTime() - start; log.info("{} took {} ms", ...); return result. Только @Around с ProceedingJoinPoint умеет proceed(), и без явного вызова proceed() целевой метод не выполнится.

  • @Async — что важно знать?

    Работает через прокси (как @Transactional) — не работает при self-invocation. Нужен @EnableAsync. Default executor может быть неподходящим — часто настраивают свой TaskExecutor.

  • @Autowired + несколько подходящих бинов — что делать?

    @Qualifier("beanName") на точке инжекта, или @Primary на одном из бинов, или имя поля/параметра должно совпадать с именем бина.

  • CORS — что это и когда возникает?

    Cross-Origin Resource Sharing: браузер блокирует запросы к другому домену. Сервер разрешает через заголовки: Access-Control-Allow-Origin, Access-Control-Allow-Methods. Preflight запрос (OPTIONS) перед POST/PUT с нестандартными заголовками; простые запросы preflight не требуют.

  • Что такое Dirty / non-repeatable / phantom read?

    Dirty — чтение незакоммиченных данных. Non-repeatable — два чтения одной строки дают разный результат. Phantom — два SELECT с WHERE возвращают разное число строк.

  • Dirty / non-repeatable / phantom read — пример каждого?

    Dirty: чтение незакоммиченных данных. Non-repeatable: два чтения одной строки дают разный результат. Phantom: два чтения с WHERE возвращают разное число строк.

  • В чём разница: HAProxy vs Nginx vs Envoy?

    HAProxy: L4/L7, production-proven, простая конфигурация. Nginx: L7, статика + reverse proxy. Envoy: L4/L7, gRPC, service mesh (Istio). В VK — все три в разных сценариях.

  • Что такое HTTP-методы и идемпотентность?

    GET (получить, идемпотентен), POST (создать, НЕ идемпотентен), PUT (заменить полностью, идемпотентен), PATCH (частично обновить, обычно нет), DELETE (удалить, идемпотентен). Идемпотентность — это когда повторный вызов с тем же запросом даёт тот же эффект на состояние сервера.

  • Что такое IoC и DI?

    IoC — контейнер управляет жизненным циклом. DI — зависимости внедряются извне. Три способа: конструктор (лучший), сеттер, поле (@Autowired). Constructor injection: поля final, явные зависимости, легко тестировать.

  • JSON vs XML — в чём разница?

    JSON компактнее, читабельнее, нативно поддерживается в JavaScript. XML — стандартизированный, есть схемы (XSD), namespace, можно валидировать. Для REST почти всегда JSON, для SOAP — обязательно XML.

  • OpenAPI / Swagger — для чего?

    Спецификация REST API в формате YAML/JSON. Описывает endpoints, методы, параметры, тела запросов/ответов, коды ответов. Swagger UI — интерактивная документация на основе этой спецификации, из которой можно отправлять запросы.

  • Что такое Propagation?

    REQUIRED (default) — присоединяется к текущей или создаёт новую. REQUIRES_NEW — всегда новая, приостанавливает текущую (аудит/логирование). NESTED — savepoint внутри текущей (откат внешней откатывает и вложенную). SUPPORTS — присоединяется если транзакция есть, нет — работает без неё. MANDATORY требует существующую (иначе исключение), NEVER — наоборот, бросает исключение при наличии транзакции.

  • Что такое Propagation-уровни транзакций?

    REQUIRED (default) — присоединяется или создаёт. REQUIRES_NEW — всегда новая, приостанавливает текущую. NESTED — savepoint. SUPPORTS, MANDATORY, NOT_SUPPORTED, NEVER.

  • PUT vs PATCH — когда что?

    PUT: замена ресурса целиком. Отправляешь ВСЕ поля, даже неизменённые. Идемпотентен (повтор даёт тот же результат). PATCH: частичное обновление. Отправляешь ТОЛЬКО изменённые поля. Обычно НЕ идемпотентен.

  • REST vs gRPC — когда что?

    REST — публичные API, простая отладка. gRPC — внутренний inter-service (быстрее, типизация через protobuf, streaming).

  • В чём разница: REST vs SOAP?

    REST: HTTP, JSON, легковесный, stateless, гибкий. SOAP: XML, WSDL, строгий контракт, WS- Security. В банках: REST для новых API, SOAP для legacy (АБС, процессинг). Junior AQA: REST — основной, но упомянуть знание SOAP — плюс.

  • Scope: prototype в singleton?

    Prototype-бин создастся один раз при инжекте. Решение: Provider<T>, ObjectFactory<T>, @Lookup.

  • Что такое Scope бинов?

    singleton (default), prototype, request, session, application, websocket. Инжект prototype в singleton: через Provider<T>, ObjectFactory<T> или @Lookup. Иначе prototype создастся один раз.

  • Что такое Scopes бина?

    singleton (default — один на контекст), prototype (новый при каждом запросе), request (один на HTTP-запрос), session, application, websocket. Web-скоупы доступны автоматически в web-контексте. Важно: инжект prototype в singleton через Provider<T> или ObjectFactory<T>; для prototype контейнер не вызывает destroy-колбэки.

  • Scopes бина. Какой default?

    singleton (default), prototype, request, session, application, websocket.

  • Что такое self-invocation?

    this.method() минует прокси → @Transactional/@Async/@Cacheable не работают. Решения: вынести метод в другой бин (рекомендуемый), инжектить self через @Lazy или ObjectProvider, использовать AspectJ compile-time weaving.

  • Singleton-бин: потокобезопасен ли?

    НЕТ. Singleton означает один экземпляр на контекст, но это НЕ делает его потокобезопасным. Если есть mutable state (поля, не final) — race condition, ведь объект делят все потоки. Решения: stateless бины (без полей-состояний), ThreadLocal, synchronized или атомарные типы.

  • Что такое Spring Boot 3 + Java 21?

    GraalVM native image, Virtual Threads support (spring.threads.virtual.enabled=true), Jakarta EE вместо javax.

  • Spring Boot auto-configuration — как устроен?

    @EnableAutoConfiguration + @Conditional. Конфиги описаны в META- INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (ранее — spring.factories).

  • Spring Data — как работает?

    Интерфейс extends JpaRepository<Entity, ID>. Spring создаёт прокси в рантайме. Имя метода парсится: findByEmailAndStatus → JPQL. @Query для сложных запросов (JPQL по умолчанию, native по флагу). Pageable → Page/Slice. JpaRepository добавляет flush() и batch-операции.

  • Что такое @SpringBootApplication?

    @Configuration + @EnableAutoConfiguration + @ComponentScan. Автоконфигурация через @Conditional: если DataSource в classpath — настроит JPA. Кандидаты берутся из META-INF/spring/...AutoConfiguration.imports (Spring Boot 3+). По умолчанию сканируется пакет класса и подпакеты.

  • Что такое @Transactional?

    Прокси (JDK/CGLIB). Открывает транзакцию, commit/rollback. self-call минует прокси. Rollback на RuntimeException/Error; checked — нужен rollbackFor.

  • @Transactional + долгий REST-вызов внутри — чем опасно?

    Транзакция удерживает соединение к БД всё время REST-вызова (секунды). Пул соединений исчерпается → все потоки ждут → сервис висит (connection starvation). Внешние вызовы нужно выносить за пределы транзакции.

  • @Transactional на private методе — что произойдёт?

    Ничего — транзакция не создастся. CGLIB-прокси наследует класс, но private методы не переопределяемы → прокси их не видит. JDK Dynamic Proxy работает через интерфейс — private вообще не в интерфейсе. Приложение поднимется штатно, метод выполнится, но без транзакции.

  • @Transactional — под капотом?

    Spring создаёт прокси-обёртку. JDK dynamic proxy (если интерфейс) или CGLIB (наследование). Прокси: открывает транзакцию (PlatformTransactionManager), вызывает метод, commit при успехе, rollback при ошибке. AspectJ weaving — только при явной настройке mode=ASPECTJ.

  • @Transactional — прокси?

    Spring создаёт прокси (JDK/CGLIB). Прокси открывает транзакцию, вызывает метод, commit/rollback. self-call минует прокси → @Transactional/@Cacheable/@Async не работают. Решение: вынести в другой бин.

  • Что такое Автоконфигурация Spring Boot?

    @EnableAutoConfiguration + @Conditional. Если DataSource в classpath — автоматически настроит JPA. Список: META-INF/spring/...AutoConfiguration.imports (Spring Boot 3+, раньше spring.factories).

  • В какой момент происходит коммит @Transactional?

    После успешного завершения метода (без исключений). Прокси: try { beginTransaction; target.method(); commit; } catch { rollback; }. Rollback по умолчанию: только RuntimeException и Error (unchecked); на checked-исключения отката нет — нужен явный rollbackFor.

  • В чём плюшка Spring Boot?

    Автоконфигурация — Spring Boot сам подключает компоненты в зависимости от того, что есть на classpath. Стартеры — готовые наборы зависимостей (spring-boot-starter-web подтягивает Spring MVC, Tomcat, Jackson). Встроенный сервер (Tomcat/Jetty) — приложение запускается как обычный jar. Boot надстраивается над Spring Framework, а не заменяет его.

  • В чём разница 401 и 403?

    401 Unauthorized — НЕ АУТЕНТИФИЦИРОВАН (не знаем кто ты — нет токена / он невалидный). Сделай login и приходи снова. 403 Forbidden — АУТЕНТИФИЦИРОВАН, но нет ПРАВ. Знаем кто ты, но эту операцию делать не можешь. Сначала аутентификация (401), затем проверка прав (403).

  • В чём разница Proxy и Decorator?

    Оба — обёртка над другим объектом, реализуют тот же интерфейс, различие в намерении. Proxy НЕ меняет поведение оригинала, а управляет доступом к нему: контроль доступа, ленивая инициализация, кэширование. Decorator, наоборот, добавляет новое поведение к методам.

  • В чём разница PUT и PATCH?

    PUT — полная замена ресурса. Передаём весь объект целиком. Если не указать поле — оно станет null. PATCH — частичное обновление. Передаём только изменяемые поля, остальное остаётся.

  • В чём разница REST и SOAP?

    REST — архитектурный стиль на HTTP, обычно JSON, гибкий, контракт через OpenAPI/Swagger. SOAP — протокол на XML с собственным envelope (Header + Body), строгий контракт через WSDL и поддержкой WS-Security (подпись и шифрование XML).

  • Два @Transactional метода в одном классе: A() вызывает B(). Сколько транзакций?

    Одна. Вызов this.B() минует прокси → @Transactional на B() не работает. B() выполняется в транзакции A() (Propagation.REQUIRED по умолчанию), которая открывается при внешнем вызове A() через прокси.

  • Что такое Жизненный цикл бина?

    BeanDefinition → инстанцирование → DI → Aware-интерфейсы → BPP.postProcessBefore → @PostConstruct → InitializingBean → init-method → BPP.postProcessAfter (здесь оборачивание в прокси, AOP) → ГОТОВ → @PreDestroy → DisposableBean → destroy-method.

  • Из чего состоит HTTP-запрос?

    Стартовая строка: метод + URL + версия (GET /users HTTP/1.1). Headers (Content-Type, Accept, Authorization). Пустая строка. Body (для POST/PUT/PATCH). Ответ — статус + версия + headers + body.

  • Как Spring Boot узнаёт, что и как настраивать?

    Через @EnableAutoConfiguration (входит в @SpringBootApplication) + @Conditional. Конфигурации перечислены в META-INF/spring/...AutoConfiguration.imports (или старом spring.factories).

  • Как Spring Data создаёт реализацию репозитория?

    Через прокси, генерируемый в рантайме. Имя метода (findByEmailAndStatus) парсится и превращается в JPQL.

  • Как Spring создаёт реализацию репозитория, если ты только написал интерфейс?

    Через прокси, который генерируется в рантайме. Имя метода (findByEmail) парсится и превращается в SQL/JPQL.

  • Как работает @Autowired?

    Spring находит бин подходящего типа в контексте и подставляет. Если в контексте несколько бинов одного типа — нужна @Qualifier или @Primary, иначе ошибка. С Spring 4.3+ @Autowired на единственном конструкторе можно не писать.

  • Как работает @ComponentScan?

    Сканирует пакеты (по умолчанию — пакет класса с @SpringBootApplication) в поисках @Component, @Service, @Repository, @Controller.

  • Как работает @Transactional под капотом?

    Spring создаёт прокси (JDK dynamic proxy для интерфейсов или CGLIB для классов). Прокси открывает транзакцию перед методом, коммитит после или откатывает при исключении.

  • Как работает автоконфигурация?

    @EnableAutoConfiguration (входит в @SpringBootApplication) + @Conditional. Список конфигов в META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (в Spring Boot 3+, раньше был spring.factories).

  • Как разрешить конфликт, если бинов несколько?

    @Primary — пометить «приоритетный» бин. @Qualifier("name") — точечно выбрать конкретный. @Profile("prod") — активировать в определённом окружении. @ConditionalOnProperty / @ConditionalOnMissingBean — условное создание.

  • Как сделать REST-эндпоинт?

    Класс с @RestController, метод с @GetMapping/@PostMapping. Параметры — @PathVariable, @RequestParam, @RequestBody. Возвращаемый объект сериализуется в JSON через Jackson.

  • Как создать бин в Spring?

    (1) Аннотация на классе: @Component, @Service, @Repository, @Controller — Spring найдёт через component scan. (2) Метод с @Bean внутри @Configuration — явное создание (для бинов из чужих библиотек или сложной инициализации).

  • Какие HTTP-методы знаешь?

    GET — получение данных, тело не предполагается. POST — создание, отправка данных в body (не идемпотентен). PUT — полное обновление / создание (идемпотентен). PATCH — частичное обновление. DELETE — удаление. HEAD — как GET, но без body (только headers).

  • Какие propagation знаешь?

    REQUIRED (default) — использует существующую транзакцию или создаёт новую. REQUIRES_NEW — приостанавливает текущую и создаёт новую независимую транзакцию. Полезно для аудита: должно записаться, даже если основная транзакция упала.

  • Какие scope у зависимостей в Maven?

    compile (default) — доступно везде, идёт в финальный jar. test — только для тестов. provided — для компиляции, но не в финальный jar (например, servlet-api — его даёт Tomcat в рантайме). runtime — нужно в рантайме, но не при компиляции.

  • Какие scopes у бинов?

    singleton (по умолчанию — один на контекст), prototype (новый при каждом запросе), request, session, application, websocket — для веб-приложений.

  • Какие аннотации для тестов в Spring Boot?

    @SpringBootTest — поднимает весь контекст приложения. Долго, но полноценно. @WebMvcTest — только web-слой (контроллеры), без БД. @DataJpaTest — только JPA-слой, с in-memory БД. MockMvc — имитация HTTP-запросов в тестах.

  • Какие группы статус-кодов есть?

    1xx — информационные. 2xx — успех (200 OK, 201 Created, 204 No Content). 3xx — редирект (301 постоянный, 302 временный, 304 Not Modified). 4xx — ошибка клиента (400, 401, 403, 404, 409). 5xx — ошибка сервера (500, 503).

  • Какие принципы у REST?

    Stateless — сервер не хранит сессию клиента, каждый запрос самодостаточен. Cacheable — ответы могут кэшироваться. Uniform interface — единый интерфейс через HTTP-методы и URL. Client-server и layered system дополняют набор.

  • Какие скоупы бывают у бинов?

    Singleton (default) — один экземпляр на контекст. Prototype — новый объект на каждый запрос get. Request, Session, Application — для веб-приложений, привязаны к жизни HTTP-запроса, сессии и ServletContext соответственно.

  • Какие способы инъекции бинов есть?

    Field (через @Autowired на поле) — короткий, но плохой. Setter (через @Autowired на сеттере) — гибкий, но позволяет создать неполностью сконфигурированный объект. Constructor — лучший: final-поля, гарантированно полностью сконфигурированный объект и лёгкое тестирование без контейнера.

  • Какой DI лучше?

    Constructor injection. Поля можно final, явно видны зависимости, легко тестировать без контекста (new Service(mockRepo)), невозможен циклический DI при старте (сигнал о проблеме в дизайне). С Spring 4 при единственном конструкторе @Autowired можно не писать.

  • Какой способ DI предпочтительнее?

    Constructor injection. Поля можно сделать final, явно видны обязательные зависимости, легко тестировать без Spring-контекста.

  • Какой способ внедрения предпочтительнее?

    Constructor injection. Поля можно final, явно видны обязательные зависимости, удобно тестировать без контекста, нет скрытых циклических зависимостей.

  • Какой способ внедрения предпочтительнее и почему?

    Constructor injection: immutable-поля (final), явные обязательные зависимости, удобство в тестах без mock-контейнера, нет циклических зависимостей.

  • Когда нужен REQUIRES_NEW?

    Когда нужна НЕЗАВИСИМАЯ транзакция, которая сохранится даже при rollback основной: текущая транзакция приостанавливается, открывается новая с отдельным соединением и коммитится сама по себе. Примеры: запись аудит-лога (должна остаться при ошибке), отправка уведомления, счётчик попыток.

  • Конфликт зависимостей: как искать?

    mvn dependency:tree — показывает дерево зависимостей. Ищем разные версии одной библиотеки. Gradle: ./gradlew dependencies. Решение: exclusion в Maven/Gradle, dependencyManagement/BOM, force в Gradle. Классика: Jackson 2.x разных версий; Maven берёт ближайшую в дереве (nearest-wins).

  • Можно ли в GET передать body?

    Спецификация не запрещает, но рекомендует не использовать. Многие фреймворки и прокси игнорируют body в GET. Если параметров много — лучше POST с явной семантикой («поиск с телом») или query string.

  • Почему constructor injection лучше field injection?

    (1) Можно делать поля final — иммутабельность. (2) Видны все зависимости — если их 10, конструктор большой, это сигнал «класс делает слишком много» (SRP). (3) Легко тестировать без Spring — обычный new SomeService(mockA, mockB) без поднятия контекста.

  • Почему REST stateless?

    Без сессии на сервере любой запрос можно отправить на любой сервер кластера. Это позволяет легко горизонтально масштабироваться: добавил инстанс — балансер начал слать на него. Состояние держит клиент (например, в JWT).

  • Почему @Transactional не работает при self-invocation?

    Вызов this.method() идёт минуя прокси. Решение: вынести метод в другой бин или инжектить self через ApplicationContext / @Lazy self.

  • Почему @Transactional не работает при вызове метода того же класса?

    Self-invocation идёт минуя прокси. Решение: вынести метод в отдельный бин или inject self.

  • Что такое Расскажи упрощённый жизненный цикл бина?

    (1) Spring находит определение (BeanDefinition). (2) Вызывает конструктор. (3) Инжектит зависимости (setter / field). (4) BeanPostProcessor.before. (5) @PostConstruct — пользовательская инициализация (afterPropertiesSet). (6) BeanPostProcessor.after. (7) Готовый бин. (8) @PreDestroy при остановке.

  • Чем @Async может удивить?

    Не работает self-invocation (как у @Transactional). Нужен @EnableAsync. Default executor может быть неподходящим — часто настраивают свой.

  • Чем @RestController отличается от @Controller?

    @RestController = @Controller + @ResponseBody. То есть результаты методов сразу сериализуются HttpMessageConverter'ами (по умолчанию Jackson в JSON) и отдаются в body ответа. @Controller сам по себе ожидает имя view (для рендера HTML).

  • Что делает @ComponentScan?

    Сканирует указанный пакет (по умолчанию — пакет класса, на котором стоит) и все подпакеты на предмет аннотаций @Component, @Service, @Repository, @Controller. Найденные классы регистрируются как бины в контексте.

  • Что делает @SpringBootApplication?

    Это композиция трёх аннотаций: @Configuration + @EnableAutoConfiguration + @ComponentScan.

  • Что произойдёт при вызове @Transactional-метода из того же класса?

    Транзакция НЕ откроется. Внутри одного бина вызов this.method() идёт напрямую на объект, в обход AOP-прокси. Это любимая ловушка на собесах — самая частая ошибка. Контекст поднимается нормально, ошибка тихая и чисто рантаймовая.

  • Что такое @Autowired и @Qualifier?

    @Autowired — внедрение зависимости. Если бинов несколько — Spring не знает какой выбрать нужен @Qualifier("имяБина") или @Primary на одном из бинов.

  • Что такое DI?

    Dependency Injection — конкретная реализация IoC. Зависимости передаются объекту: через конструктор, сеттер или поле. ApplicationContext в Spring — это, по сути, Map<id, bean>. Spring сам создаёт бины и инжектит их друг в друга.

  • Что такое dirty read, non-repeatable read, phantom read?

    Dirty: чтение незакоммиченных изменений другой транзакции. Non-repeatable: повторное чтение той же строки даёт другой результат. Phantom: повторный SELECT с WHERE возвращает другое количество строк.

  • Что такое IoC?

    Inversion of Control — инверсия управления. Вместо того чтобы класс сам создавал свои зависимости (new), он получает их извне — фреймворк сам решает, кого с кем связать.

  • Что такое IoC и DI?

    IoC — принцип: контейнер сам управляет жизненным циклом объектов. DI — реализация: зависимости в объект внедряются извне (через конструктор / сеттер / поле).

  • Что такое Jakarta EE и чем отличается от Spring?

    Jakarta EE (раньше Java EE) — набор стандартов-спецификаций корпоративной Java (сервлеты, JPA, JMS, EJB), реализуемых серверами приложений (GlassFish, WildFly). Spring — самостоятельный фреймворк поверх обычной Java, не требующий сервера приложений и не являющийся реализацией спецификаций Jakarta EE.

  • Что такое REST?

    Архитектурный стиль построения веб-сервисов. Идея: ресурсы (нечто, что имеет URL), действия над ними (через HTTP-методы), без сохранения состояния на сервере. Не протокол, а набор принципов.

  • Что такое Spring Boot?

    Spring + автоконфигурация + встроенный сервер (Tomcat/Jetty/Undertow) + стартеры. Минимизирует boilerplate.

  • Что такое Spring Boot и чем он отличается от Spring?

    Spring Boot — это Spring + автоконфигурация + встроенный сервер (Tomcat/Jetty) + удобные стартеры. Минимизирует boilerplate. По сути «Spring без боли с XML».

  • Что такое Spring Cloud и для чего он?

    Набор инструментов для микросервисов: service discovery (Eureka), конфиг-сервер, API Gateway, Circuit Breaker. На Junior достаточно знать «что это и зачем».

  • Что такое Spring и зачем он нужен?

    Фреймворк, который берёт на себя «инфраструктурный код»: создание объектов, связи между ними (DI), управление транзакциями, обработку HTTP, доступ к БД. Освобождает от boilerplate и работает поверх обычной JVM, не заменяя её.

  • Что такое @SpringBootApplication?

    Композиция трёх аннотаций: @SpringBootConfiguration (= @Configuration), @EnableAutoConfiguration (запуск автоконфигурации), @ComponentScan (сканирование пакетов начиная с этого класса).

  • Что такое @Transactional?

    Аннотация, которая открывает транзакцию вокруг метода. На успешный возврат — COMMIT, на RuntimeException — ROLLBACK. Реализуется через AOP-прокси: вызов идёт через прокси, который и управляет транзакцией.

  • Что такое автоконфигурация?

    Spring Boot имеет много готовых «конфигурационных рецептов». Они применяются автоматически, если выполнены условия (@Conditional): например, есть нужные классы на classpath, нет своего бина, заданы свойства. Настраивает инфраструктурные бины стартеров.

  • Что такое идемпотентность?

    Многократный вызов даёт тот же результат, что и однократный. Не путать с «безопасностью» (никак не меняет состояние) — GET и safe, и идемпотентен. PUT и DELETE идемпотентны (повторное PUT того же — тот же результат), а POST — нет.

  • Что такое стартер?

    Готовый набор зависимостей под задачу. Например, spring-boot-starter-web подтянет Spring MVC, встроенный Tomcat, Jackson. Один импорт — и веб-приложение работает.

  • Что такое стартер в Spring Boot?

    Готовый набор зависимостей под задачу. Например, spring-boot-starter-web подтянет Spring MVC, Tomcat, Jackson и т.д. Один импорт — и веб-приложение работает.

  • Сервис вызывает свой метод с @Transactional через this.save(). Что произойдёт с транзакцией?

    Вызов обойдёт Spring proxy, поэтому transactional advice не применится к внутреннему вызову.

новые гайды и свежие вопросы с собесов — первыми в Telegram Смотреть гайды Подписаться