Add cycles to core-beans: the circular-dependency failure report, what allow-circular-references repairs and hides, and four fixes on Boot 4.1
Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Uu7q8vPeREyT4218EJPzz1
This commit is contained in:
+22
-2
@@ -1,11 +1,12 @@
|
||||
# core-beans
|
||||
|
||||
Companion project for two articles on **[ankurm.com](https://ankurm.com)**.
|
||||
Companion project for three articles on **[ankurm.com](https://ankurm.com)**.
|
||||
|
||||
| Article | What it demonstrates |
|
||||
|---|---|
|
||||
| [Spring Bean Scopes: Singleton, Prototype, Request, Session and the Prototype-in-Singleton Trap](https://ankurm.com/spring-bean-scopes-singleton-prototype-request-session-prototype-in-singleton-trap/) | instance counts for every scope, five ways to get a fresh prototype inside a singleton, a singleton that leaks one caller's data into another's, and request scope without a proxy failing at start-up |
|
||||
| [Spring Bean Lifecycle in Boot 4: @PostConstruct, InitializingBean, SmartLifecycle and Shutdown Order](https://ankurm.com/spring-bean-lifecycle-postconstruct-smartlifecycle-shutdown-order/) | every callback in order from a real run, `@PostConstruct` running before the proxy exists, the non-static `BeanPostProcessor` warning, `SmartLifecycle` phases measured, and a request in flight during graceful shutdown with virtual threads |
|
||||
| [Circular Dependencies in Spring Boot 4: Why Startup Fails and 4 Ways to Fix It](https://ankurm.com/spring-boot-4-circular-dependencies-startup-fails-4-fixes/) | the start-up failure report for a three-service ring, the creation order behind it, what `allow-circular-references` does and does not repair (a half-built bean, `@Async` versus `@Cacheable`, an INFO line that swallows an exception), and four fixes run side by side: redesign, events, `@Lazy`, `ObjectProvider` |
|
||||
|
||||
Every console block, exception message and count quoted in those articles came out of `output/`,
|
||||
and every file there is regenerated by one script. Most are written by the test suite, so if a
|
||||
@@ -39,6 +40,7 @@ mvn test # runs the scenarios and rewrites the test-writte
|
||||
| `web/` | `@RequestScope`, `@SessionScope`, `@ApplicationScope` beans and a diagnostic `/scopes` controller, plus the un-proxied request bean that fails at start-up |
|
||||
| `lifecycle/` | `KitchenSink` (every callback), the post-processor traps, `PhasedWorker` and `NeverStops` for `SmartLifecycle` |
|
||||
| `shutdown/` | a web application with a `/slow` endpoint and two `SmartLifecycle` beans at different phases |
|
||||
| `cycles/` | one package per scenario: `broken/` (the three-service ring), `allowed/` (field cycles with the flag on), `redesign/`, `events/`, `lazy/` and `provider/` (the four fixes), `beanmethods/` (a cycle written as `@Bean` methods) |
|
||||
|
||||
## Endpoints
|
||||
|
||||
@@ -51,7 +53,7 @@ Both endpoints exist only to be called by the tests. They have no authorisation.
|
||||
|
||||
## Captured output
|
||||
|
||||
Files 01-17 and 19 (tests) and 18 (`capture-metadata.sh`). Timing rows assert coarse thresholds, not exact milliseconds; treat them as indicative.
|
||||
Files 01-17 and 19-35 (tests) and 18 (`capture-metadata.sh`). Timing rows assert coarse thresholds, not exact milliseconds; treat them as indicative.
|
||||
|
||||
| File | What it shows |
|
||||
|---|---|
|
||||
@@ -74,6 +76,24 @@ Files 01-17 and 19 (tests) and 18 (`capture-metadata.sh`). Timing rows assert co
|
||||
| [`17-worker-phase-vs-web-server.txt`](output/17-worker-phase-vs-web-server.txt) | SmartLifecycle beans with the default phase and with phase 1000, while a request is in flight |
|
||||
| [`18-property-defaults.txt`](output/18-property-defaults.txt) | Property defaults read from spring-configuration-metadata.json (Boot 4.1.1 jars) |
|
||||
| [`19-bean-post-processors.txt`](output/19-bean-post-processors.txt) | The BeanPostProcessors registered in a plain Spring Boot context, in the order they run |
|
||||
| [`20-boot-cycle-failure-report.txt`](output/20-boot-cycle-failure-report.txt) | Three constructor-injected services in a ring: what Spring Boot prints when start-up fails |
|
||||
| [`21-cycle-exception-and-creation-order.txt`](output/21-cycle-exception-and-creation-order.txt) | The exception behind the report, and the order in which the container started creating beans |
|
||||
| [`22-bean-method-cycle-failure-report.txt`](output/22-bean-method-cycle-failure-report.txt) | A two-bean cycle written as `@Bean` methods |
|
||||
| [`23-lazy-initialization-hides-the-cycle.txt`](output/23-lazy-initialization-hides-the-cycle.txt) | `spring.main.lazy-initialization=true` on the same ring: it starts, then fails on first use |
|
||||
| [`24-allow-circular-half-built-bean.txt`](output/24-allow-circular-half-built-bean.txt) | A field cycle with the flag off and on: what each `@PostConstruct` sees |
|
||||
| [`25-allow-circular-async-raw-reference.txt`](output/25-allow-circular-async-raw-reference.txt) | The same cycle with `@Async`: repaired silently at start-up, a raw-version error under lazy initialisation |
|
||||
| [`26-allow-circular-cacheable-early-proxy.txt`](output/26-allow-circular-cacheable-early-proxy.txt) | The same cycle with `@Cacheable`: the injected reference is the proxy |
|
||||
| [`27-fix-redesign.txt`](output/27-fix-redesign.txt) | Fix 1: extract the one thing the second bean needed |
|
||||
| [`28-fix-events.txt`](output/28-fix-events.txt) | Fix 2: an event instead of a call, and what the publisher sees when the listener throws |
|
||||
| [`29-fix-lazy.txt`](output/29-fix-lazy.txt) | Fix 3: `@Lazy` on the parameter, and the proxy class that arrives |
|
||||
| [`30-fix-object-provider.txt`](output/30-fix-object-provider.txt) | Fix 4: `ObjectProvider`, resolving in the constructor, and a final class |
|
||||
| [`31-lazy-on-a-final-class.txt`](output/31-lazy-on-a-final-class.txt) | `@Lazy` on a parameter whose type is a final class |
|
||||
| [`32-lazy-injection-point-versus-lazy-bean.txt`](output/32-lazy-injection-point-versus-lazy-bean.txt) | `@Lazy` on the injection point versus on the bean, with a target that cannot be built |
|
||||
| [`33-dispatcher-handler-cycle.txt`](output/33-dispatcher-handler-cycle.txt) | A cycle through `List<Handler>` and its `ObjectProvider` repair |
|
||||
| [`34-depends-on-cycle.txt`](output/34-depends-on-cycle.txt) | `@DependsOn` in both directions: no injection involved |
|
||||
| [`35-lazy-used-during-construction.txt`](output/35-lazy-used-during-construction.txt) | `@Lazy` on the parameter, but the bean calls the dependency from `@PostConstruct` |
|
||||
| [`36-main-property-defaults.txt`](output/36-main-property-defaults.txt) | The defaults of `spring.main.allow-circular-references` and `spring.main.lazy-initialization`, from Boot's own metadata |
|
||||
| [`37-early-reference-bytecode.txt`](output/37-early-reference-bytecode.txt) | Which post-processors hand out an early reference, and the `BeanCurrentlyInCreationException` handler in `preInstantiateSingleton` |
|
||||
|
||||
## Licence
|
||||
|
||||
|
||||
Reference in New Issue
Block a user