Практический проект по курсу SprBut: один модуль на каждый раздел презентации плюс итоговый модуль с расширенным заданием по всему курсу.
Презентация: SprBut — план курса и слайды
Разделы «Spring MVC», «WebFlux», «Spring Security» и «Spring Cloud» добавлены в презентацию после восьмой лекции; модули 20–23 сделаны по ним.
Курс отвечает на один вопрос: почему код в исходниках и поведение в рантайме — это не одно и то же. Первая половина показывает, чем эту разницу создают (рефлексия, аннотации, генерация кода), вторая — как ею управляет Spring (контейнер, прокси, конфигурация, автоконфигурация).
Каждый модуль устроен одинаково:
- примеры — по классу на пункт слайда, с docblock'ом, объясняющим назначение;
- тесты — покрывают каждый пример, проверяя ровно одно поведение;
- расширенный пример — итог модуля: рабочий инструмент, собирающий тему целиком;
- README — цитата из презентации, таблица примеров, ключевые выводы.
| № | Модуль | Тема | Расширенный пример |
|---|---|---|---|
| 01 | reflection-basics | Reflection и метаданные в runtime | JSON-сериализатор целиком на рефлексии |
| 02 | javabeans | JavaBeans, record, Builder | Сравнение четырёх стилей одного класса |
| 03 | reflection-api | java.lang.reflect: Field, Method, Constructor |
Обходчик графа объектов |
| 04 | reflection-advanced | JPMS, дженерики, MethodHandles, Proxy | Динамический прокси со своим InvocationHandler |
| 05 | annotations-basics | @Target, @Retention, @Inherited |
Проверка объектов по аннотациям |
| 06 | annotations-advanced | @Repeatable, TYPE_USE, композиции |
Раскрытие вложенных мета-аннотаций |
| 07 | annotation-processor | AbstractProcessor, генерация кода и байткода |
Свой процессор с JavaPoet |
| 08 | apt-usage | Регистрация, раунды, Filer |
Сборка, использующая сгенерированный код |
| 09 | reflection-vs-apt | Runtime, compile-time, байткод | Замер цены каждого подхода |
| 10 | lombok-mapstruct | Готовые генераторы | Слой отображения на MapStruct |
| 11 | ioc-di | IoC, DI, фабрики, пул, Dagger | Работающий IoC-контейнер на 150 строк |
| 12 | di-injection | Конструктор, сеттер, поле, циклы | Аудитор точек внедрения |
| 13 | bean-annotations | @Bean, @Scope, @Qualifier, @Conditional |
Отчёт о содержимом контейнера |
| 14 | bean-lifecycle | Восемь шагов жизненного цикла | Шкала с проверкой инвариантов порядка |
| 15 | spring-modules-aop | Модули Spring, AOP, прокси | Своя @Retryable и четыре вида self-invocation |
| 16 | configuration | Приоритеты источников, профили | «Откуда взялось это значение» |
| 17 | spring-annotations | Стереотипы, @Configuration, условия |
Каталог с раскрытием композиций |
| 18 | boot-startup | Последовательность запуска Boot | Восстановление таймлайна старта |
| 19 | autoconfiguration | Стартеры, imports, условия |
Программный отчёт об условиях |
| 20 | spring-mvc | DispatcherServlet, контроллеры, ResponseEntity |
Таблица маршрутов, снятая с приложения |
| 21 | webflux | Mono, Flux, неблокирующий ввод-вывод |
Backpressure, показанный счётчиком |
| 22 | spring-security | Цепочка фильтров, роли, @PreAuthorize |
Цепочка фильтров, выписанная по именам |
| 23 | spring-cloud | Discovery, балансировка, circuit breaker | Предохранитель, пойманный за работой |
| 24 | testing | @SpringBootTest, срезы, @MockitoBean |
Один функционал четырьмя способами |
| 25 | common-mistakes | Пять типичных ошибок контейнера | Диагност падений в духе FailureAnalyzer |
| 26 | aot-native | AOT, native image, javax → jakarta |
Аудит готовности к native image |
| 27 | capstone | Итоговое задание: SprBut Tracker | Карта контейнера: приложение о самом себе |
Разделы презентации, у которых материала на несколько занятий, разбиты на отдельные модули: Reflection — на 01–04, аннотации — на 05–06, annotation processor — на 07–09, IoC и DI — на 11–14, аннотации Spring — на 16–17, веб-разработка — на 20–21.
Три примера выходят за рамки слайдов: они показывают, что у темы есть и другой конец, о котором на занятии сказано вскользь.
| Пример | Модуль | О чём |
|---|---|---|
BytecodeProcessor |
07 | Filer.createClassFile и ByteBuddy: класс кладётся готовым, javac в этой ветке не участвует |
ObjectPool |
11 | Управление временем жизни без подбора зависимостей; аренда через AutoCloseable возвращает объект в пул сама |
WiringModule |
11 | Тот же граф зависимостей, но собранный Dagger'ом на этапе компиляции |
Модуль 27 — SprBut Tracker — трекер задач, в котором встречается каждая тема курса, от собственной аннотации с аспектом до подсказок для native image.
Итоговый расширенный пример —
ContextMap:
приложение, которое рефлексией по живому контейнеру рассказывает о себе само —
чем стали его бины, во что они обёрнуты, какие методы перехвачены, какие маршруты
просматривает DispatcherServlet и через какую цепочку фильтров запрос до него
добирается.
Требуется JDK 25 и Maven 3.9+. Стек — Spring Boot 4.1.
mvn test # все модули
mvn -pl 27-capstone test # один модуль
mvn -pl 27-capstone spring-boot:runМодули 01–09 активно используют рефлексию, поэтому корневой pom.xml открывает
базовые пакеты JDK через --add-opens — без этого setAccessible падал бы
на InaccessibleObjectException (см. модуль 04).
Код следует правилам из RULE.md: Elegant Objects и SOLID, неизменяемые
объекты, final-классы с одним-четырьмя атрибутами, docblock'и вместо
инлайн-комментариев, «злые тесты» с одним утверждением на тест.
Там, где правило спорит с темой курса, побеждает тема — и расхождение объясняется прямо в docblock'е. Рефлексия, JavaBeans-геттеры и статические точки входа существуют в модулях именно потому, что они и есть предмет разговора: модуль про JavaBeans без сеттеров не показал бы ничего.