<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ankit Verma</title>
    <description>The latest articles on DEV Community by Ankit Verma (@ankit_verma_e2fa7fb2aa95d).</description>
    <link>https://dev.to/ankit_verma_e2fa7fb2aa95d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3973400%2F62bb2cd4-9517-49ee-9812-abecef838b1b.jpg</url>
      <title>DEV Community: Ankit Verma</title>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ankit_verma_e2fa7fb2aa95d"/>
    <language>en</language>
    <item>
      <title>Recap — M0 Foundations</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Tue, 16 Jun 2026 09:40:01 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/recap-m0-foundations-ee6</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/recap-m0-foundations-ee6</guid>
      <description>&lt;p&gt;This module built one thing, from many angles: the &lt;strong&gt;container&lt;/strong&gt; — the part of Spring that creates your objects, wires them together, and hands them out. Eight articles each zoomed in on a different corner of it. This recap zooms back out. The goal here is not to re-explain each topic, but to show how they are all the same idea seen from different sides, so the whole module collapses into a picture you can hold in your head at once.&lt;/p&gt;

&lt;p&gt;So before the details, here is the single sentence the entire module hangs on: &lt;strong&gt;the container is a factory that runs at startup, and almost every feature you met is just that factory doing a little extra work while it builds a bean.&lt;/strong&gt; Keep that sentence close. Everything below is a way of filling it in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The factory, in one picture
&lt;/h2&gt;

&lt;p&gt;Picture an assembly line that runs exactly once, when your application boots. You hand it a list of what to build and how the pieces fit. It builds every object your app is made of, connects them, sets them on a shelf, and hands them out on request for the rest of the program's life.&lt;/p&gt;

&lt;p&gt;That assembly line is the container. The objects it builds and manages are &lt;strong&gt;beans&lt;/strong&gt;. An object you create yourself with &lt;code&gt;new&lt;/code&gt; is not a bean — Spring never touched it — and that distinction is the thread running through every trap in this module.&lt;/p&gt;

&lt;p&gt;The factory does four things at startup, and the order matters: it reads recipes, works out who needs whom, builds from the bottom up, and caches each result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ApplicationContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// already built and wired&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the time &lt;code&gt;run&lt;/code&gt; returns, the work is done. Asking for a bean is instant because the building already happened. Every other topic in the module is a detail about &lt;em&gt;how&lt;/em&gt; that one startup pass works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we hand the work over at all
&lt;/h2&gt;

&lt;p&gt;The module opened with a question of control. Left alone, a class builds its own collaborators with &lt;code&gt;new&lt;/code&gt; — and in doing so it welds together two unrelated decisions: &lt;em&gt;what&lt;/em&gt; it needs, and &lt;em&gt;which&lt;/em&gt; exact thing it gets and how that thing is built.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpClient&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pulling those two decisions apart is the whole point. The class should declare &lt;em&gt;what&lt;/em&gt; it needs and let something outside choose and supply the &lt;em&gt;which&lt;/em&gt;. Handing that choice to the framework is &lt;strong&gt;Inversion of Control&lt;/strong&gt; — your code stops creating its own collaborators. The way the collaborator then arrives is &lt;strong&gt;Dependency Injection&lt;/strong&gt; — it is passed in from outside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// declares the need, receives it&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IoC is the idea; DI is the delivery. And the delivery has a preferred form for a mechanical reason, not a stylistic one: &lt;strong&gt;constructor injection&lt;/strong&gt; makes the field &lt;code&gt;final&lt;/code&gt;, makes the object impossible to build half-wired, and makes it testable with a plain &lt;code&gt;new&lt;/code&gt; in a unit test. That preference for the constructor is a decision the rest of the module keeps cashing in.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a single bean comes to life
&lt;/h2&gt;

&lt;p&gt;Once you accept that the factory builds your beans, the natural next question is &lt;em&gt;how&lt;/em&gt; it builds one. The answer is a fixed four-stage sequence — the &lt;strong&gt;bean lifecycle&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instantiate&lt;/strong&gt; — construct the raw object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Populate&lt;/strong&gt; — inject field- and setter-style dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initialize&lt;/strong&gt; — run setup now that everything is wired.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destroy&lt;/strong&gt; — run teardown at an orderly shutdown.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The order is the lesson. A field-injected dependency is &lt;code&gt;null&lt;/code&gt; if you touch it in the constructor, because populate (stage 2) has not run yet. Setup that needs dependencies belongs in &lt;code&gt;@PostConstruct&lt;/code&gt; (stage 3), where wiring is guaranteed complete. Teardown mirrors it in &lt;code&gt;@PreDestroy&lt;/code&gt; (stage 4).&lt;/p&gt;

&lt;p&gt;Notice how this rewards constructor injection again: it folds populate into instantiate, so a constructor-injected bean is never half-there. The lifecycle is just the factory's per-bean routine, and most of its surprises come from forgetting which stage runs when.&lt;/p&gt;

&lt;h2&gt;
  
  
  How many, and how long
&lt;/h2&gt;

&lt;p&gt;The lifecycle describes one bean's journey. &lt;strong&gt;Scope&lt;/strong&gt; answers the other two questions about it: how many instances exist, and how long each lives.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Singleton&lt;/strong&gt; — one instance per container, the default, shared by everyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototype&lt;/strong&gt; — a fresh instance on every request, built on demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request&lt;/strong&gt; and &lt;strong&gt;session&lt;/strong&gt; — one instance per HTTP request or per user session.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Shared," in the singleton line, is the dangerous word, and it leads to the module's most common bug. Because one singleton serves every thread at once, any &lt;em&gt;mutable&lt;/em&gt; field on it is a race condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CartService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;itemCount&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// one field, every thread, lost updates&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;itemCount&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule that falls out is short: &lt;strong&gt;keep singletons stateless.&lt;/strong&gt; Immutable shared state — your injected dependencies — is exactly what a singleton is good at; mutable shared state is the trap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which container is doing all this
&lt;/h2&gt;

&lt;p&gt;Up to here, "the container" has been a single idea. In Spring's code it wears two names, and the difference matters. &lt;strong&gt;&lt;code&gt;BeanFactory&lt;/code&gt;&lt;/strong&gt; is the minimal contract — store recipes, build beans lazily on request. &lt;strong&gt;&lt;code&gt;ApplicationContext&lt;/code&gt;&lt;/strong&gt; extends it and &lt;em&gt;staffs&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;That staffing is the whole reason you always use the &lt;code&gt;ApplicationContext&lt;/code&gt;. Features like &lt;code&gt;@Autowired&lt;/code&gt; and &lt;code&gt;@PostConstruct&lt;/code&gt; are not part of the factory core — each is a plugin called a &lt;strong&gt;&lt;code&gt;BeanPostProcessor&lt;/code&gt;&lt;/strong&gt; that gets a crack at every bean during the lifecycle. The bare &lt;code&gt;BeanFactory&lt;/code&gt; registers none of them, so it silently ignores your annotations. The &lt;code&gt;ApplicationContext&lt;/code&gt; registers them all automatically, and it builds singletons &lt;strong&gt;eagerly&lt;/strong&gt; at startup — so a broken wiring fails at boot, on your machine, not three days later in production.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ApplicationContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.shop"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// every annotation honored, every singleton already built&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the same fail-fast instinct constructor injection showed with circular dependencies: surface the problem at the safest possible moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  How you tell the factory what exists — and how it finds it
&lt;/h2&gt;

&lt;p&gt;The factory needs recipes. Where they come from is the &lt;strong&gt;configuration style&lt;/strong&gt;, and Spring has had three, each fixing the last one's pain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;XML&lt;/strong&gt; — all wiring in an external file. Central, but verbose and string-typed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annotations&lt;/strong&gt; — &lt;code&gt;@Component&lt;/code&gt; and friends mark the class itself. The default for your own code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java config&lt;/strong&gt; — &lt;code&gt;@Bean&lt;/code&gt; methods inside a &lt;code&gt;@Configuration&lt;/code&gt; class. The way to register classes you cannot annotate, like third-party objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three end as the same internal bean definitions, which is why one app mixes them freely. Java config carries one subtlety worth keeping: Spring wraps a &lt;code&gt;@Configuration&lt;/code&gt; class in a &lt;strong&gt;proxy&lt;/strong&gt; so that a call from one &lt;code&gt;@Bean&lt;/code&gt; method to another returns the &lt;em&gt;shared&lt;/em&gt; bean instead of building a second one.&lt;/p&gt;

&lt;p&gt;For the annotation style, &lt;strong&gt;component scanning&lt;/strong&gt; is how the factory actually finds your marked classes. &lt;code&gt;@ComponentScan&lt;/code&gt; walks a &lt;strong&gt;base package&lt;/strong&gt; and everything beneath it — and only ever downward, which is why the main class lives in the root package, and why a class above the scan's start point silently never registers. The &lt;strong&gt;stereotypes&lt;/strong&gt; — &lt;code&gt;@Service&lt;/code&gt;, &lt;code&gt;@Repository&lt;/code&gt;, &lt;code&gt;@Controller&lt;/code&gt; — are just &lt;code&gt;@Component&lt;/code&gt; with a role attached, scanned identically, though &lt;code&gt;@Repository&lt;/code&gt; earns exception translation as a bonus.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the factory connects the beans
&lt;/h2&gt;

&lt;p&gt;With every bean found and defined, the last job is wiring them — &lt;strong&gt;autowiring&lt;/strong&gt;. The rule is resolution &lt;strong&gt;by type&lt;/strong&gt;: the container finds the one bean whose type fits a dependency and injects it. One match and the wiring is silent.&lt;/p&gt;

&lt;p&gt;The interesting part is the tie-break, when two beans fit one slot. The container refuses to guess and fails fast; you break the tie three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parameter name&lt;/strong&gt; — a quiet fallback that matches the injection point's name to a bean name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@Primary&lt;/code&gt;&lt;/strong&gt; — one global default, declared on the bean.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@Qualifier&lt;/code&gt;&lt;/strong&gt; — a named choice at the injection point, which overrides &lt;code&gt;@Primary&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And when a dependency might legitimately be absent, &lt;code&gt;Optional&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;ObjectProvider&amp;lt;T&amp;gt;&lt;/code&gt; make that explicit instead of crashing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two threads that run through everything
&lt;/h2&gt;

&lt;p&gt;Step back and two ideas turn out to connect almost every topic.&lt;/p&gt;

&lt;p&gt;The first is the &lt;strong&gt;proxy&lt;/strong&gt; — a same-shaped stand-in the factory can hand you instead of the bare bean. It is not one feature; it is the same trick reused everywhere. It is how &lt;code&gt;@Transactional&lt;/code&gt; opens a transaction around your method. It is how a request-scoped bean gets injected into a singleton — the proxy resolves to the right per-request instance on each call. It is how a &lt;code&gt;@Configuration&lt;/code&gt; class avoids building a bean twice. And its &lt;em&gt;timing&lt;/em&gt; — created after &lt;code&gt;@PostConstruct&lt;/code&gt; runs — is why init code self-calling a proxied method quietly skips the wrapper. Once you see the proxy, a dozen "how does Spring even do that?" questions share one answer.&lt;/p&gt;

&lt;p&gt;The second is &lt;strong&gt;fail-fast&lt;/strong&gt;: surface a mistake at the earliest, safest moment. Eager singleton startup catches broken wiring at boot. Constructor injection turns a circular dependency into a boot-time error instead of a production &lt;code&gt;StackOverflowError&lt;/code&gt;. An ambiguous autowire stops the app rather than picking the wrong bean. The strictness is the safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  The traps, as one family
&lt;/h2&gt;

&lt;p&gt;Almost every gotcha in this module is the same mistake wearing different clothes — a mismatch between &lt;strong&gt;when injection happens&lt;/strong&gt; and &lt;strong&gt;when you use the result&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A field-injected dependency touched in the constructor is &lt;code&gt;null&lt;/code&gt; — populate runs &lt;em&gt;after&lt;/em&gt; the constructor.&lt;/li&gt;
&lt;li&gt;A mutable field on a singleton races — one instance is wired once and shared across every thread.&lt;/li&gt;
&lt;li&gt;A prototype injected into a singleton freezes — injection is a one-time event, so you get one prototype forever; reach for &lt;code&gt;ObjectProvider&lt;/code&gt; to pull a fresh one each call.&lt;/li&gt;
&lt;li&gt;A proxied method self-called inside &lt;code&gt;@PostConstruct&lt;/code&gt; skips the proxy — the wrapper is not built yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See them together and they stop being four facts to memorize. They are all consequences of one truth: &lt;strong&gt;for a singleton, wiring happens exactly once, at startup.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The one picture to keep
&lt;/h2&gt;

&lt;p&gt;If you keep only one thing from this module, keep the factory. The container reads recipes, builds your beans bottom-up in dependency order, can wrap each one in a proxy, caches the results, and fails fast when something does not fit. Inversion of Control is &lt;em&gt;why&lt;/em&gt; you hand the work over; dependency injection is &lt;em&gt;how&lt;/em&gt; the pieces arrive; the lifecycle is &lt;em&gt;how&lt;/em&gt; one bean is assembled; scope is &lt;em&gt;how many and how long&lt;/em&gt;; the &lt;code&gt;ApplicationContext&lt;/code&gt; is the fully-staffed factory that runs it; configuration, scanning, and autowiring are how it learns what to build and connects it all.&lt;/p&gt;

&lt;p&gt;Everything heavier you meet from here — AOP, transactions, web request handling, data access — is a variation on this one startup pass. The factory does not go away. It just keeps finding new work to do while it builds your beans.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>@Autowired resolution, @Qualifier/@Primary, injection types + circular-dependency gotcha</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Mon, 15 Jun 2026 10:44:01 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/autowired-resolution-qualifierprimary-injection-types-circular-dependency-gotcha-249h</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/autowired-resolution-qualifierprimary-injection-types-circular-dependency-gotcha-249h</guid>
      <description>&lt;p&gt;The last article left the container in a tidy state. Scanning has finished, and every class you marked is now a &lt;strong&gt;bean definition&lt;/strong&gt; sitting in the container, names and all. But a definition is just a recipe. The moment the container starts actually building beans, it hits the question this article is about: to build &lt;code&gt;OrderService&lt;/code&gt;, it needs to pass something into the &lt;code&gt;PaymentGateway&lt;/code&gt; slot in its constructor — so &lt;em&gt;which&lt;/em&gt; bean does it reach for?&lt;/p&gt;

&lt;p&gt;When exactly one bean fits, the answer is obvious and you never think about it. The interesting part is everything around that happy path: how the container makes the match, what happens when two beans fit the same slot, and how you steer the choice when it can't decide on its own.&lt;/p&gt;

&lt;p&gt;That whole job — the container finding and supplying the beans a dependency needs, instead of you naming each one by hand — is called &lt;strong&gt;autowiring&lt;/strong&gt;. You meet it for real the first time Spring refuses to start, complaining it found more than one bean of some type and doesn't know which you meant. To fix that on purpose instead of by trial and error, you need to see how resolution actually works.&lt;/p&gt;

&lt;p&gt;This article walks it end to end: the match by type, why &lt;code&gt;@Autowired&lt;/code&gt; is often already implied, the ambiguity that breaks the match, the three tools that break the tie, what to do when a bean might be missing — and finally a deeper look at the circular-dependency trap the dependency-injection article only cracked open.&lt;/p&gt;

&lt;h2&gt;
  
  
  The happy path: resolution by type
&lt;/h2&gt;

&lt;p&gt;Start with the rule from the dependency-injection article, now seen from the container's side. When the container builds a bean and reaches a dependency, it looks through every bean it knows about for one whose &lt;strong&gt;type&lt;/strong&gt; fits, and injects that one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// "I need a PaymentGateway"&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is exactly one &lt;code&gt;PaymentGateway&lt;/code&gt; bean in the container, the match is unambiguous and the wiring just happens. You declared a need by type; the container found the one bean that satisfies it and handed it over. That is autowiring in its simplest, invisible form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where did &lt;code&gt;@Autowired&lt;/code&gt; go?
&lt;/h2&gt;

&lt;p&gt;You may have noticed there is no &lt;code&gt;@Autowired&lt;/code&gt; on that constructor. That is not an oversight. When a class has a &lt;strong&gt;single constructor&lt;/strong&gt;, Spring treats it as an injection point automatically — it assumes the parameters are dependencies to resolve, no annotation required.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;@Autowired&lt;/code&gt; only needs to appear in the cases Spring cannot infer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On a class with &lt;strong&gt;more than one constructor&lt;/strong&gt;, to mark which one the container should call.&lt;/li&gt;
&lt;li&gt;On a &lt;strong&gt;field or setter&lt;/strong&gt;, where there is no sole constructor for Spring to assume.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;                                  &lt;span class="c1"&gt;// needed here only if there are other constructors&lt;/span&gt;
    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The useful way to hold it: &lt;code&gt;@Autowired&lt;/code&gt; marks an &lt;strong&gt;injection point&lt;/strong&gt; — a spot that says "fill this in from the container." A parameter on a sole constructor is an injection point implicitly. Everywhere else, the annotation is how you point at one.&lt;/p&gt;

&lt;h2&gt;
  
  
  When two beans fit one slot
&lt;/h2&gt;

&lt;p&gt;Now the situation that breaks the happy path. Suppose two classes implement the same interface, and both are beans:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeGateway&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdyenGateway&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; still asks for a single &lt;code&gt;PaymentGateway&lt;/code&gt;. The container searches by type and now finds &lt;strong&gt;two&lt;/strong&gt; candidates. It has no basis to prefer one, and it will not guess. It fails at startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;NoUniqueBeanDefinitionException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="nx"&gt;single&lt;/span&gt; &lt;span class="nx"&gt;matching&lt;/span&gt; &lt;span class="nx"&gt;bean&lt;/span&gt;
&lt;span class="nx"&gt;but&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stripeGateway&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;adyenGateway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the fail-fast philosophy again — an ambiguous wiring is caught at boot, on your machine, not silently resolved into the wrong gateway in production. Spring gives you three ways to resolve it, and they are worth knowing as a set, because they layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tie-breaker 1: the parameter name
&lt;/h2&gt;

&lt;p&gt;Before you reach for any annotation, Spring has a quiet fallback already running. When the type matches several beans, it tries to narrow them by &lt;strong&gt;name&lt;/strong&gt; — matching the name of the injection point against the bean names. Recall from the scanning article that a scanned bean is named after its class, decapitalized: &lt;code&gt;StripeGateway&lt;/code&gt; becomes &lt;code&gt;stripeGateway&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;stripeGateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// parameter name matches a bean name&lt;/span&gt;
        &lt;span class="c1"&gt;// resolves to the stripeGateway bean&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Name the parameter &lt;code&gt;stripeGateway&lt;/code&gt; and the ambiguity disappears: the container matches it to the bean of that name. It works, but lean on it carefully. It depends on parameter names surviving compilation (Spring Boot compiles with that turned on, so they do), and it is &lt;strong&gt;subtle&lt;/strong&gt; — renaming a parameter silently rewires the application. It is fine as a fallback; it is a poor way to express intent. For that, be explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tie-breaker 2: &lt;code&gt;@Primary&lt;/code&gt; — declare a default winner
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@Primary&lt;/code&gt; marks one bean as the default to use whenever several fit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="nd"&gt;@Primary&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeGateway&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdyenGateway&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now any unqualified &lt;code&gt;PaymentGateway&lt;/code&gt; injection, anywhere in the app, gets Stripe. The key trait is that &lt;code&gt;@Primary&lt;/code&gt; lives on the &lt;strong&gt;bean&lt;/strong&gt; — one declaration, applied everywhere that type is needed. It is the right tool when there is one obvious default and only rare exceptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tie-breaker 3: &lt;code&gt;@Qualifier&lt;/code&gt; — name the one you want
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@Primary&lt;/code&gt; decides globally. &lt;code&gt;@Qualifier&lt;/code&gt; decides at a single &lt;strong&gt;injection point&lt;/strong&gt;. You give the beans qualifier names and then ask for one by name right where you need it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"stripe"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeGateway&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"adyen"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdyenGateway&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"stripe"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// this slot wants Stripe&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the two combine cleanly. When both are present, &lt;code&gt;@Qualifier&lt;/code&gt; at the injection point &lt;strong&gt;wins over&lt;/strong&gt; &lt;code&gt;@Primary&lt;/code&gt;. The idiom that falls out: mark the everyday default with &lt;code&gt;@Primary&lt;/code&gt;, and use &lt;code&gt;@Qualifier&lt;/code&gt; only at the few spots that need the exception. Most of the code stays quiet; the deviations are explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the bean might not be there
&lt;/h2&gt;

&lt;p&gt;The mirror image of ambiguity is absence. If a required dependency has &lt;strong&gt;no&lt;/strong&gt; matching bean, the container fails at boot with &lt;code&gt;NoSuchBeanDefinitionException&lt;/code&gt; — the same fail-fast instinct. Usually that is exactly what you want. But occasionally a dependency is genuinely optional: a metrics sink that may or may not be configured, say. Spring has three ways to say "inject it if it exists, otherwise carry on":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@Autowired(required = false)&lt;/code&gt; — leaves a field or setter unset if no bean is found.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Optional&amp;lt;PaymentGateway&amp;gt;&lt;/code&gt; — arrives empty when the bean is absent.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ObjectProvider&amp;lt;PaymentGateway&amp;gt;&lt;/code&gt; — a lazy handle you ask for the bean only when you need it (the same type the bean-scopes article used to pull a fresh prototype on demand).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// empty if no gateway bean exists&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer &lt;code&gt;Optional&lt;/code&gt; or &lt;code&gt;ObjectProvider&lt;/code&gt; over &lt;code&gt;required = false&lt;/code&gt;: they keep the field &lt;code&gt;final&lt;/code&gt; and make the "might be absent" part visible in the type, instead of hiding it behind a field that is sometimes &lt;code&gt;null&lt;/code&gt;. (And note the &lt;code&gt;List&amp;lt;PaymentGateway&amp;gt;&lt;/code&gt; form from the DI article is a different case entirely — it asks for &lt;em&gt;all&lt;/em&gt; matching beans on purpose, so several matches are the answer, not an error.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Injection types, seen through resolution
&lt;/h2&gt;

&lt;p&gt;The DI article already made the case for constructor injection over setters and fields, so this is just the same picture from the resolver's angle: the matching algorithm above is identical no matter where the injection point sits. &lt;code&gt;@Qualifier&lt;/code&gt; and &lt;code&gt;@Primary&lt;/code&gt; work the same on a constructor parameter, a setter, or a field.&lt;/p&gt;

&lt;p&gt;What changes is &lt;em&gt;when&lt;/em&gt; resolution runs and how safely. &lt;strong&gt;Constructor&lt;/strong&gt; injection resolves everything at construction, so the object is never half-built and the fields can be &lt;code&gt;final&lt;/code&gt;. &lt;strong&gt;Setter&lt;/strong&gt; injection runs during the populate stage, which suits a truly optional or reconfigurable dependency. &lt;strong&gt;Field&lt;/strong&gt; injection is the most concise and the least testable. The resolution rules don't pick a style for you — but as the next section shows, the style you pick decides how one particular failure behaves.&lt;/p&gt;

&lt;h2&gt;
  
  
  The circular-dependency gotcha, in full
&lt;/h2&gt;

&lt;p&gt;The DI article showed one slice of this: two beans that depend on each other, wired through constructors, fail at boot. Here is the complete picture, because the outcome depends entirely on the injection style — and that is the whole lesson.&lt;/p&gt;

&lt;p&gt;Say &lt;code&gt;A&lt;/code&gt; needs &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;B&lt;/code&gt; needs &lt;code&gt;A&lt;/code&gt;. With &lt;strong&gt;constructor injection on both sides&lt;/strong&gt;, neither object can be built first: building &lt;code&gt;A&lt;/code&gt; needs a finished &lt;code&gt;B&lt;/code&gt;, which needs a finished &lt;code&gt;A&lt;/code&gt;, and round it goes. The container detects the loop and stops:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;BeanCurrentlyInCreationException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="nx"&gt;Requested&lt;/span&gt; &lt;span class="nx"&gt;bean&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;currently&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;creation&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;there&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;unresolvable&lt;/span&gt; &lt;span class="nx"&gt;circular&lt;/span&gt; &lt;span class="nx"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That looks like an obstacle. It is actually the good case — the cycle is exposed the instant you start the app.&lt;/p&gt;

&lt;p&gt;Now switch the two beans to &lt;strong&gt;field injection&lt;/strong&gt; and watch the failure quietly vanish:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="no"&gt;B&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because field injection happens &lt;em&gt;after&lt;/em&gt; construction, Spring has a move available that constructors deny it. It builds the raw &lt;code&gt;A&lt;/code&gt; first, then — before &lt;code&gt;A&lt;/code&gt; is fully wired — exposes a reference to that half-built &lt;code&gt;A&lt;/code&gt;. It builds &lt;code&gt;B&lt;/code&gt;, setting &lt;code&gt;B&lt;/code&gt;'s field to the early &lt;code&gt;A&lt;/code&gt; reference. With &lt;code&gt;B&lt;/code&gt; now complete, it finishes wiring &lt;code&gt;A&lt;/code&gt; by setting &lt;code&gt;A&lt;/code&gt;'s field to the finished &lt;code&gt;B&lt;/code&gt;. The cycle resolves, and the application starts as if nothing were wrong.&lt;/p&gt;

&lt;p&gt;That "as if nothing were wrong" is the trap. A circular dependency is a real design flaw — two beans so entangled that neither is whole without the other — and field injection lets it ship undetected. Constructor injection would have failed loudly at boot and forced the conversation. This is one more reason the earlier articles pushed constructors so hard: the strictness is the safety.&lt;/p&gt;

&lt;p&gt;Spring offers an escape hatch, &lt;code&gt;@Lazy&lt;/code&gt;, for when you must break a cycle without redesigning right now. Put &lt;code&gt;@Lazy&lt;/code&gt; on one of the two injection points and the container injects a &lt;strong&gt;proxy&lt;/strong&gt; — the same stand-in trick from the first article — instead of the real bean, deferring the real lookup until the first method call. By then both beans exist, so the loop never has to be resolved at construction time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Lazy&lt;/span&gt; &lt;span class="no"&gt;B&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// injects a proxy now, resolves B on first use&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treat that as a patch, not a cure. The honest fix is to break the cycle: pull the shared logic into a third bean both can depend on, or let one side publish an &lt;strong&gt;event&lt;/strong&gt; the other listens for, the way the &lt;code&gt;ApplicationContext&lt;/code&gt; article wired &lt;code&gt;OrderService&lt;/code&gt; to email without either knowing the other. A mutual dependency almost always means a responsibility is living in the wrong class.&lt;/p&gt;

&lt;p&gt;It is worth knowing that recent Spring Boot takes your side here: since 2.6 it &lt;strong&gt;forbids circular references by default&lt;/strong&gt;, so even a field-injected cycle fails at startup unless you deliberately set &lt;code&gt;spring.main.allow-circular-references=true&lt;/code&gt;. The framework now nudges everyone toward the fix instead of the papering-over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;Autowiring is the container resolving each dependency &lt;strong&gt;by type&lt;/strong&gt;: one matching bean and the wiring is silent, with &lt;code&gt;@Autowired&lt;/code&gt; implied on a sole constructor and only spelled out for extra constructors, fields, and setters. When two beans fit one slot, the container fails fast rather than guess — and you break the tie three ways: the &lt;strong&gt;parameter name&lt;/strong&gt; (a subtle fallback), &lt;strong&gt;&lt;code&gt;@Primary&lt;/code&gt;&lt;/strong&gt; (one global default on the bean), or &lt;strong&gt;&lt;code&gt;@Qualifier&lt;/code&gt;&lt;/strong&gt; (a named choice at the injection point that overrides &lt;code&gt;@Primary&lt;/code&gt;). When a bean might be missing, &lt;code&gt;Optional&lt;/code&gt; or &lt;code&gt;ObjectProvider&lt;/code&gt; make the absence explicit instead of crashing.&lt;/p&gt;

&lt;p&gt;The deepest point is the one about cycles. Resolution itself doesn't care which injection style you used — but a circular dependency does. Constructor injection turns it into a boot-time error you cannot miss; field injection papers over it and lets a design flaw ship. That asymmetry, now reinforced by Boot's default of refusing cycles outright, is the last and strongest argument for wiring through the constructor.&lt;/p&gt;

&lt;p&gt;With that, the container's whole story is on the table: how it learns what your beans are, builds them, scopes them, and now connects them to each other. The next article steps back from the individual mechanisms and ties the entire Foundations module into one mental model — a recap of how every piece we have built fits together.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Component scanning &amp; stereotypes</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:30:48 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/component-scanning-stereotypes-79k</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/component-scanning-stereotypes-79k</guid>
      <description>&lt;p&gt;The last article left a thread dangling. It showed that the annotation style marks a class as a bean by putting &lt;code&gt;@Component&lt;/code&gt; — or one of its cousins — right on the class, and then said the container finds those marked classes by &lt;em&gt;component scanning&lt;/em&gt;. It promised that scanning was "its own topic, the very next article." This is that article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component scanning&lt;/strong&gt; is the step where Spring walks through your code, finds the classes you marked as beans, and registers each one with the container. It is the bridge between "I annotated a class" and "the container knows that class exists." Without it, an &lt;code&gt;@Service&lt;/code&gt; is just an annotation sitting on a class Spring never bothers to look at.&lt;/p&gt;

&lt;p&gt;You meet scanning the first time a class you wrote refuses to show up. You added &lt;code&gt;@Service&lt;/code&gt;, you asked the container for it, and Spring answers that there is no such bean. Almost always the class is sitting in a package the scan never visited. To fix that with intent instead of guesswork, you need to know what scanning actually does and where it actually looks.&lt;/p&gt;

&lt;p&gt;This article walks the whole mechanism: how the scan finds your classes, the &lt;strong&gt;stereotype&lt;/strong&gt; annotations that mark them, the one stereotype that quietly does more than mark, where the search begins, and the traps that come from searching too narrowly or too widely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mark and the search are two halves of one thing
&lt;/h2&gt;

&lt;p&gt;Recall the single job of &lt;code&gt;@Component&lt;/code&gt;: it labels a class as something the container should build and manage — a bean. But a label does nothing on its own. Something has to go looking for it.&lt;/p&gt;

&lt;p&gt;That something is the &lt;strong&gt;component scanner&lt;/strong&gt;. At startup, before a single bean is built, the scanner walks a set of packages, inspects every class it finds, and for each class wearing &lt;code&gt;@Component&lt;/code&gt; it writes down a &lt;strong&gt;bean definition&lt;/strong&gt; — the recipe card from the earlier articles. When the scan finishes, the container holds a definition for every annotated class, exactly as if you had spelled them all out in Java config by hand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On its own, that class is inert. The annotation says "I am a bean"; the scan is what hears it. Miss either half — forget the annotation, or never scan the package it lives in — and the bean simply does not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning the scan on
&lt;/h2&gt;

&lt;p&gt;You rarely write the line that starts scanning, but it is worth seeing once, plainly. The annotation that switches it on is &lt;code&gt;@ComponentScan&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="nd"&gt;@ComponentScan&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.shop"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That says: walk the &lt;code&gt;com.shop&lt;/code&gt; package and everything beneath it, and register every &lt;code&gt;@Component&lt;/code&gt; you find. The string is a &lt;strong&gt;base package&lt;/strong&gt; — the root where the search begins. Scanning is &lt;strong&gt;recursive&lt;/strong&gt;, so &lt;code&gt;com.shop&lt;/code&gt;, &lt;code&gt;com.shop.orders&lt;/code&gt;, and &lt;code&gt;com.shop.billing.tax&lt;/code&gt; are all swept in by that one line.&lt;/p&gt;

&lt;p&gt;In a Spring Boot app you never actually write &lt;code&gt;@ComponentScan&lt;/code&gt;, because it is hidden inside the annotation on your main class. But it is running all the same, and knowing it is there is what makes the next trap avoidable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the search starts — and the classic trap
&lt;/h2&gt;

&lt;p&gt;The annotation on your main class, &lt;code&gt;@SpringBootApplication&lt;/code&gt;, is a bundle: it folds together &lt;code&gt;@Configuration&lt;/code&gt;, the auto-configuration switch, and &lt;code&gt;@ComponentScan&lt;/code&gt; — the last one with &lt;strong&gt;no package argument&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you give &lt;code&gt;@ComponentScan&lt;/code&gt; no package, it does not scan nothing. It defaults to the package of the class it sits on, and everything below it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.shop&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// the root package&lt;/span&gt;

&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;      &lt;span class="c1"&gt;// scans com.shop and downward&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShopApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ShopApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the reason every Boot project puts its main class in the &lt;strong&gt;root package&lt;/strong&gt;, above all the others. From there, the default scan naturally covers the whole application — &lt;code&gt;com.shop.web&lt;/code&gt;, &lt;code&gt;com.shop.billing&lt;/code&gt;, all of it.&lt;/p&gt;

&lt;p&gt;Now the trap, which catches nearly everyone once. Move that main class down into a sub-package by mistake:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.shop.web&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// oops — not the root&lt;/span&gt;

&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;       &lt;span class="c1"&gt;// scans com.shop.web and downward ONLY&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShopApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scanning now starts at &lt;code&gt;com.shop.web&lt;/code&gt;. Your &lt;code&gt;com.shop.billing&lt;/code&gt; package is &lt;em&gt;above&lt;/em&gt; the start point, so it is never visited, and none of its beans get registered. The symptom is a &lt;code&gt;NoSuchBeanDefinitionException&lt;/code&gt; at startup — Spring asking for a bean it was never told about. The fix is to move the main class back up to the root, or to name the packages explicitly with &lt;code&gt;@SpringBootApplication(scanBasePackages = "com.shop")&lt;/code&gt;. Either way, the cause is the same: the scan only ever looks down from where it starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stereotypes: same scan, different meaning
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@Component&lt;/code&gt; is the generic mark. On top of it, Spring ships three specialized labels — &lt;code&gt;@Service&lt;/code&gt;, &lt;code&gt;@Repository&lt;/code&gt;, and &lt;code&gt;@Controller&lt;/code&gt; — known together as the &lt;strong&gt;stereotype&lt;/strong&gt; annotations, because each names the &lt;em&gt;role&lt;/em&gt; a class plays in the usual layered design: business logic, data access, web entry point.&lt;/p&gt;

&lt;p&gt;Here is the detail that ties them to everything above. Each stereotype is itself &lt;strong&gt;meta-annotated&lt;/strong&gt; with &lt;code&gt;@Component&lt;/code&gt; — that is, &lt;code&gt;@Component&lt;/code&gt; is stamped on the annotation itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;          &lt;span class="c1"&gt;// &amp;lt;-- right here, on the annotation&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the scanner treats "annotated with &lt;code&gt;@Component&lt;/code&gt;, directly or through another annotation" as the trigger, a &lt;code&gt;@Service&lt;/code&gt; is picked up by exactly the same scan as a bare &lt;code&gt;@Component&lt;/code&gt;. There is no separate machinery for them. A stereotype &lt;em&gt;is&lt;/em&gt; a &lt;code&gt;@Component&lt;/code&gt; with a name on it.&lt;/p&gt;

&lt;p&gt;So why bother with the specialized ones? Two reasons, both real but modest. They &lt;strong&gt;document the layer&lt;/strong&gt; at a glance — &lt;code&gt;@Repository&lt;/code&gt; tells a reader "this talks to the database" in a way &lt;code&gt;@Component&lt;/code&gt; never could. And they give Spring and your tools a hook to treat a layer specially. For most classes the stereotypes are interchangeable with &lt;code&gt;@Component&lt;/code&gt;; the habit is simply to pick the one that names what the class actually does.&lt;/p&gt;

&lt;h2&gt;
  
  
  @Repository earns more than its name
&lt;/h2&gt;

&lt;p&gt;One stereotype does more than label, and it is worth knowing exactly what. When the scan registers a &lt;code&gt;@Repository&lt;/code&gt; bean, Spring also wraps it in a &lt;strong&gt;proxy&lt;/strong&gt; — the same stand-in trick from the first article — to perform &lt;strong&gt;exception translation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is the problem it solves. Every persistence technology throws its own exceptions: raw JDBC throws &lt;code&gt;SQLException&lt;/code&gt;, Hibernate throws its own &lt;code&gt;HibernateException&lt;/code&gt;, and so on. If your service layer caught those directly, it would be welded to whichever library sits underneath.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Repository&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JpaOrderRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// may hit a vendor-specific failure&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because this is a &lt;code&gt;@Repository&lt;/code&gt;, the proxy around it catches those vendor-specific exceptions on the way out and rethrows them as Spring's own &lt;code&gt;DataAccessException&lt;/code&gt; family — one consistent hierarchy, the same no matter what runs below. Swap JPA for plain JDBC tomorrow, and the exception types your service code catches do not change. That single benefit is a concrete reason to put &lt;code&gt;@Repository&lt;/code&gt; on data-access classes rather than a generic &lt;code&gt;@Component&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@Controller&lt;/code&gt; stereotype has its own special handling too — the web layer recognizes it and routes HTTP requests to its methods — but that belongs to the web module later. For now it is enough that the scan treats it like any other &lt;code&gt;@Component&lt;/code&gt;, and something downstream gives it extra meaning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every scanned bean gets a name
&lt;/h2&gt;

&lt;p&gt;When the scanner registers a bean, the container needs a name for it. By default, scanning takes the &lt;strong&gt;simple class name and decapitalizes the first letter&lt;/strong&gt;: &lt;code&gt;OrderService&lt;/code&gt; becomes the bean named &lt;code&gt;orderService&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;      &lt;span class="c1"&gt;// registered under the name "orderService"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the time you never touch the name, because injection resolves by &lt;strong&gt;type&lt;/strong&gt;, as the dependency-injection article showed. The name starts to matter only when two beans share a type and you must point at one specifically — that tie-breaking is the next article's subject — or when two names collide.&lt;/p&gt;

&lt;p&gt;The collision is worth flagging because it fails loudly. Put two classes with the &lt;em&gt;same simple name&lt;/em&gt; in different packages, and both want to be &lt;code&gt;orderService&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// com.shop.billing.OrderService   -&amp;gt; wants "orderService"&lt;/span&gt;
&lt;span class="c1"&gt;// com.shop.legacy.OrderService    -&amp;gt; also wants "orderService"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scanning refuses the ambiguity and throws &lt;code&gt;ConflictingBeanDefinitionException&lt;/code&gt; at startup. That is the fail-fast philosophy again — a name clash is caught at boot, not silently resolved into the wrong bean. When you genuinely need two such classes, give one an explicit name with &lt;code&gt;@Service("legacyOrderService")&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scanning too wide
&lt;/h2&gt;

&lt;p&gt;By default the scan registers &lt;em&gt;everything&lt;/em&gt; annotated that it finds below the base package. Usually that is what you want. But a base package set too broad will quietly pull in classes you never meant to activate — a stray &lt;code&gt;@Configuration&lt;/code&gt; in some sub-module that switches a feature on, or test-only beans that have no business in production.&lt;/p&gt;

&lt;p&gt;For that, &lt;code&gt;@ComponentScan&lt;/code&gt; accepts &lt;strong&gt;filters&lt;/strong&gt; that include or exclude classes by annotation, type, or pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ComponentScan&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;basePackages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"com.shop"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;excludeFilters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@ComponentScan&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FilterType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ANNOTATION&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// skip stray @Configuration classes&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filters are the precise tool when the default sweep grabs too much. The blunter fix is the better default: keep your base packages &lt;strong&gt;tight&lt;/strong&gt;. A narrow scan registers only what you intend, and as a bonus it costs less at startup — walking a smaller slice of the classpath is faster than walking all of it. Over-broad scanning is one of the quiet reasons a large application boots slowly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;Component scanning is how the annotation style turns marked classes into registered beans. The &lt;strong&gt;scanner&lt;/strong&gt; walks a base package and everything under it, and for every class carrying &lt;code&gt;@Component&lt;/code&gt; — directly or through a stereotype — it writes a bean definition into the container. The annotation declares the intent; the scan is what acts on it, and both halves are required.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;base package&lt;/strong&gt; is where the search starts and only ever goes downward — which is why the main class lives in the root package, and why a class above the scan's start point silently never registers. The &lt;strong&gt;stereotypes&lt;/strong&gt; — &lt;code&gt;@Service&lt;/code&gt;, &lt;code&gt;@Repository&lt;/code&gt;, &lt;code&gt;@Controller&lt;/code&gt; — are &lt;code&gt;@Component&lt;/code&gt; with a role attached; they are scanned identically, but &lt;code&gt;@Repository&lt;/code&gt; also earns exception translation, and &lt;code&gt;@Controller&lt;/code&gt; is later picked up by the web layer. Each scanned bean gets a decapitalized class name by default, and a name clash fails fast at boot.&lt;/p&gt;

&lt;p&gt;So the scan ends with the container holding a complete set of bean definitions, names and all. Which raises the question the next article answers: when the container goes to build &lt;code&gt;OrderService&lt;/code&gt; and sees it needs a &lt;code&gt;PaymentGateway&lt;/code&gt; — and &lt;em&gt;two&lt;/em&gt; beans happen to fit that type — how does it decide which one to inject? That is the job of &lt;code&gt;@Autowired&lt;/code&gt;, &lt;code&gt;@Qualifier&lt;/code&gt;, and &lt;code&gt;@Primary&lt;/code&gt;, and it is where we go next.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Configuration styles: XML annotations Java config</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Sat, 13 Jun 2026 10:31:11 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/configuration-styles-xml-annotations-java-config-5251</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/configuration-styles-xml-annotations-java-config-5251</guid>
      <description>&lt;p&gt;Every Spring application starts with the same quiet question: how does the container know which objects to build? The first articles in this module described the container as a factory that reads &lt;strong&gt;recipe cards&lt;/strong&gt; — bean definitions — and builds your objects from them. But they skipped over where those recipe cards actually come from.&lt;/p&gt;

&lt;p&gt;That source is a &lt;strong&gt;configuration style&lt;/strong&gt;: the way you tell Spring what beans exist and how they wire together. Spring has had three of them over its life — XML files, annotations, and Java config — and they arrived in that order, each fixing a pain in the one before.&lt;/p&gt;

&lt;p&gt;You meet all three whether you like it or not. A legacy module still carries an XML file. Your own code is dotted with &lt;code&gt;@Service&lt;/code&gt;. And the framework's own internals, plus most modern setup, are written in Java config. This article walks the three in the order they appeared, because each one only makes sense as an answer to the problem the previous one left behind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The recipe cards have to come from somewhere
&lt;/h2&gt;

&lt;p&gt;Recall the one rule from the first article: Spring's powers only apply to beans the container built. So before the container can build anything, something has to hand it the list of beans — their classes, their dependencies, their scopes. That list is the configuration.&lt;/p&gt;

&lt;p&gt;Here is the part that ties everything together. The &lt;em&gt;format&lt;/em&gt; of that list is separate from what the container does with it. However the definitions arrive, they all become the same internal &lt;strong&gt;bean definition&lt;/strong&gt; objects, and the same factory builds from them.&lt;/p&gt;

&lt;p&gt;So the three styles are not three different containers. They are three different ways of writing down the exact same thing. Keep that in mind, because it is why you can freely mix them in one application.&lt;/p&gt;

&lt;h2&gt;
  
  
  The XML era: configuration as a separate file
&lt;/h2&gt;

&lt;p&gt;In the beginning, Spring kept all configuration in a separate XML file, completely outside your Java code. You listed each bean by its class name and spelled out its wiring by hand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;beans&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"httpClient"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.shop.HttpClient"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"gateway"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.shop.PaymentGateway"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"httpClient"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"orderService"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.shop.OrderService"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"gateway"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read it top to bottom and it is just the recipe cards, written out longhand. Each &lt;code&gt;&amp;lt;bean&amp;gt;&lt;/code&gt; names a class. Each &lt;code&gt;&amp;lt;constructor-arg ref="..."&amp;gt;&lt;/code&gt; says "pass this other bean into the constructor." You point the container at the file, and it builds everything listed.&lt;/p&gt;

&lt;p&gt;The appeal was real. All wiring lived in &lt;strong&gt;one place&lt;/strong&gt;, visible at a glance, and you could change which class got wired where without recompiling a line of Java. Configuration was data, not code.&lt;/p&gt;

&lt;p&gt;But the costs piled up fast. The file is verbose — three lines of XML for what a constructor call says in one. The class names are &lt;strong&gt;plain strings&lt;/strong&gt;, so a typo or a renamed class fails only at startup, never at compile time. And your IDE cannot help: rename &lt;code&gt;PaymentGateway&lt;/code&gt; in Java and the XML still says the old name, silently. As applications grew to hundreds of beans, the XML grew with them, and it became its own burden to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving the marks into the code
&lt;/h2&gt;

&lt;p&gt;The next step was to stop describing beans in a far-off file and instead &lt;strong&gt;mark the class itself&lt;/strong&gt; as a bean, right where it is defined. That is what &lt;code&gt;@Component&lt;/code&gt; and its specialized cousins — &lt;code&gt;@Service&lt;/code&gt;, &lt;code&gt;@Repository&lt;/code&gt;, &lt;code&gt;@Controller&lt;/code&gt; — do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One annotation replaces a whole &lt;code&gt;&amp;lt;bean&amp;gt;&lt;/code&gt; block. The container finds these marked classes by &lt;strong&gt;component scanning&lt;/strong&gt; — walking your packages at startup and registering every annotated class as a bean. (Scanning is its own topic, the very next article; for now just take it that the container can find these marks.)&lt;/p&gt;

&lt;p&gt;This fixed the worst of XML. The bean definition now sits &lt;strong&gt;next to the code it describes&lt;/strong&gt;, so the two can never drift apart. There are no class-name strings to mistype — the annotation rides on the class, so a rename carries it along. And the dependencies are simply the constructor parameters, resolved by type, exactly as the dependency-injection article described.&lt;/p&gt;

&lt;p&gt;So annotations won for your own classes, and that is where they remain the default today. But they have one hard limit, and it is the reason a third style had to exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The wall annotations hit
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@Component&lt;/code&gt; only works if you can put it on the class. For your own code, fine. But a large share of the beans in a real application are not your classes at all — they come from libraries. A &lt;code&gt;DataSource&lt;/code&gt; from a connection-pool library, an &lt;code&gt;ObjectMapper&lt;/code&gt; from Jackson, a &lt;code&gt;RestTemplate&lt;/code&gt; from Spring itself.&lt;/p&gt;

&lt;p&gt;You cannot annotate those. You do not own the source, and editing a library's jar to add &lt;code&gt;@Component&lt;/code&gt; is not an option. Annotation-based configuration simply has nothing to say about a class you did not write.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// You want this as a bean, but you can't add @Component to it —&lt;/span&gt;
&lt;span class="c1"&gt;// HikariDataSource lives in someone else's jar.&lt;/span&gt;
&lt;span class="nc"&gt;HikariDataSource&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HikariDataSource&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setJdbcUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jdbc:postgresql://localhost/shop"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So you need a way to register a bean &lt;em&gt;without&lt;/em&gt; touching its class — and ideally one that is still plain, type-safe Java, not a string-typed file off to the side. That is exactly what Java config provides.&lt;/p&gt;

&lt;h2&gt;
  
  
  Java config: methods that build beans
&lt;/h2&gt;

&lt;p&gt;The third style writes configuration as ordinary Java, in a class marked &lt;code&gt;@Configuration&lt;/code&gt;. Inside it, each method marked &lt;code&gt;@Bean&lt;/code&gt; builds and returns one bean. The method body &lt;em&gt;is&lt;/em&gt; the recipe — you write the construction yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InfrastructureConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="nf"&gt;dataSource&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;HikariDataSource&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HikariDataSource&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setJdbcUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jdbc:postgresql://localhost/shop"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container calls &lt;code&gt;dataSource()&lt;/code&gt; once at startup, takes the returned object, and registers it as a bean named &lt;code&gt;dataSource&lt;/code&gt; — the method name. The third-party problem is gone: you never needed to annotate &lt;code&gt;HikariDataSource&lt;/code&gt;, you just called its constructor inside a method you &lt;em&gt;do&lt;/em&gt; own.&lt;/p&gt;

&lt;p&gt;Notice what this keeps from the annotation style and what it wins back from XML. It is &lt;strong&gt;plain Java&lt;/strong&gt;, so it is type-safe and your IDE refactors it like any other code — no magic strings. But like XML, it can register beans for classes you cannot annotate, and it hands you a real method body where you can run logic — read a property, pick an implementation, tune the object — before returning it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Java-config beans find each other
&lt;/h2&gt;

&lt;p&gt;A bean usually needs other beans. In Java config you wire them by writing a method that takes the dependency as a parameter, or by calling another &lt;code&gt;@Bean&lt;/code&gt; method directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InfrastructureConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="nf"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// asks for the DataSource bean&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PaymentGateway&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="nf"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;   &lt;span class="c1"&gt;// calls the other @Bean method&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameter form is the clean one: ask for &lt;code&gt;DataSource&lt;/code&gt; as a method argument and the container injects the existing bean, exactly as constructor injection does for your &lt;code&gt;@Component&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;The second form is where people get nervous. &lt;code&gt;orderService()&lt;/code&gt; calls &lt;code&gt;gateway()&lt;/code&gt; directly — and a plain Java method call would run the method again, building a &lt;em&gt;second&lt;/em&gt; &lt;code&gt;PaymentGateway&lt;/code&gt;. That would shatter the singleton guarantee: two different gateways floating around, when the whole point was one shared instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The @Configuration proxy that makes it safe
&lt;/h2&gt;

&lt;p&gt;Here the &lt;strong&gt;proxy&lt;/strong&gt; from the first article comes back to do real work. Spring does not use your &lt;code&gt;@Configuration&lt;/code&gt; class directly. At startup it wraps it in a &lt;strong&gt;proxy&lt;/strong&gt; — a same-shaped subclass — that intercepts every call to a &lt;code&gt;@Bean&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;So when &lt;code&gt;orderService()&lt;/code&gt; calls &lt;code&gt;gateway()&lt;/code&gt;, the proxy steps in front of that call. Instead of running the method body again, it checks the container: if the &lt;code&gt;gateway&lt;/code&gt; bean already exists, it hands back that cached instance. The body runs &lt;strong&gt;once&lt;/strong&gt;, no matter how many other &lt;code&gt;@Bean&lt;/code&gt; methods call it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="nf"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;   &lt;span class="c1"&gt;// proxy returns the SAME gateway bean, not a new one&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is why inter-bean method calls are safe inside a &lt;code&gt;@Configuration&lt;/code&gt; class — and &lt;em&gt;only&lt;/em&gt; inside one. The same call from a plain class, or from a class marked &lt;code&gt;@Component&lt;/code&gt; instead of &lt;code&gt;@Configuration&lt;/code&gt;, gets no proxy and really does run the method twice. (Spring lets you switch the proxy off with &lt;code&gt;@Configuration(proxyBeanMethods = false)&lt;/code&gt; when you know no &lt;code&gt;@Bean&lt;/code&gt; method calls another — it trims a little startup work, at the cost of this guarantee.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Which style, when
&lt;/h2&gt;

&lt;p&gt;These three styles all feed the same container, and a single application happily uses more than one at once. The modern division of labor is settled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Annotations&lt;/strong&gt; (&lt;code&gt;@Component&lt;/code&gt; and friends) for your own application classes — the default, because the mark lives right on the code it describes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java config&lt;/strong&gt; (&lt;code&gt;@Configuration&lt;/code&gt; + &lt;code&gt;@Bean&lt;/code&gt;) for everything you cannot annotate: third-party objects, and any bean whose creation needs real logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XML&lt;/strong&gt; essentially never in new code. You learn to read it only because older codebases — and a lot of the internet — still speak it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The thing to hold onto is that the choice is about &lt;em&gt;where the recipe is written&lt;/em&gt;, not about what you get out. Whichever style registers a bean, it lands in the container as the same kind of bean definition, builds the same way, and can be wired into beans declared by any other style.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;Configuring Spring means handing the container its recipe cards, and the &lt;strong&gt;configuration style&lt;/strong&gt; is just the form those cards take. Spring has offered three, each answering the last one's weakness. &lt;strong&gt;XML&lt;/strong&gt; put all wiring in one external file — central and recompile-free, but verbose, string-typed, and blind to refactoring. &lt;strong&gt;Annotations&lt;/strong&gt; moved the mark onto the class itself, killing the drift and the typos, but they only work on classes you own. &lt;strong&gt;Java config&lt;/strong&gt; writes each bean as a &lt;code&gt;@Bean&lt;/code&gt; method in a &lt;code&gt;@Configuration&lt;/code&gt; class — type-safe Java that can register anything, including third-party objects, and run logic while it builds.&lt;/p&gt;

&lt;p&gt;The one mechanism worth remembering is the &lt;code&gt;@Configuration&lt;/code&gt; proxy: it intercepts calls between &lt;code&gt;@Bean&lt;/code&gt; methods so a shared bean is built once, not every time it is referenced. That single trick is what lets Java config read like ordinary method calls while still honoring the container's singleton promise.&lt;/p&gt;

&lt;p&gt;All three styles end in the same place — bean definitions in one container. Which leaves the question we kept deferring: when you use the annotation style, how does the container actually &lt;em&gt;find&lt;/em&gt; your &lt;code&gt;@Component&lt;/code&gt; classes scattered across dozens of packages? That is component scanning, and it is where we go next.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>ApplicationContext vs BeanFactory</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Thu, 11 Jun 2026 21:14:09 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/applicationcontext-vs-beanfactory-3h38</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/applicationcontext-vs-beanfactory-3h38</guid>
      <description>&lt;p&gt;Every article so far has talked about "the container" — the factory that builds and wires your beans. In Spring's actual code, that factory has two names. &lt;strong&gt;&lt;code&gt;BeanFactory&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;ApplicationContext&lt;/code&gt;&lt;/strong&gt; are both interfaces that mean "the container," and sooner or later you meet both. &lt;code&gt;SpringApplication.run(...)&lt;/code&gt; hands you an &lt;code&gt;ApplicationContext&lt;/code&gt;. Older tutorials, framework internals, and the bottom of stack traces talk about &lt;code&gt;BeanFactory&lt;/code&gt;. The Javadoc of each keeps pointing at the other.&lt;/p&gt;

&lt;p&gt;So which one is &lt;em&gt;the&lt;/em&gt; container? Both — at different levels. &lt;code&gt;BeanFactory&lt;/code&gt; is the minimal core: just the machinery that stores recipes and builds beans. &lt;code&gt;ApplicationContext&lt;/code&gt; is built on top of it: the same factory, plus everything a real application needs around it. This article walks through what each one actually is, and the one difference that fails &lt;em&gt;silently&lt;/em&gt; — the reason almost nobody should ever touch the bare factory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The container's contract is an interface
&lt;/h2&gt;

&lt;p&gt;Strip the factory from the first article down to its essence and ask: what is the &lt;em&gt;smallest&lt;/em&gt; thing it must be able to do? Hold the recipes, build beans from them, and hand them out when asked. Spring writes that contract down as an interface, and it is startlingly small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BeanFactory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;requiredType&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;containsBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isSingleton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// ... a few more lookup variants, nothing else&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read what is there: lookups. Nothing about annotations, nothing about configuration files, nothing about proxies. That is the point. &lt;strong&gt;&lt;code&gt;BeanFactory&lt;/code&gt;&lt;/strong&gt; is the minimal contract for a bean container — store bean definitions, build each bean on demand, resolve its dependencies, hand it out.&lt;/p&gt;

&lt;p&gt;One behavioral detail is worth flagging now, because it becomes a real difference later: a plain &lt;code&gt;BeanFactory&lt;/code&gt; is &lt;strong&gt;lazy&lt;/strong&gt;. It does not build anything up front. A singleton gets built the first time somebody asks for it, and not a moment before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Driving the bare factory by hand
&lt;/h2&gt;

&lt;p&gt;The contract has a real, concrete implementation inside Spring called &lt;code&gt;DefaultListableBeanFactory&lt;/code&gt;. You can use it directly, and doing so once is the fastest way to understand what it is — and what it isn't:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;DefaultListableBeanFactory&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DefaultListableBeanFactory&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerBeanDefinition&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gateway"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RootBeanDefinition&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerBeanDefinition&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"orders"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RootBeanDefinition&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the factory from the first article, operated manually. You hand it recipe cards — the &lt;strong&gt;bean definitions&lt;/strong&gt; from before — and when you call &lt;code&gt;getBean&lt;/code&gt;, it looks at &lt;code&gt;OrderService&lt;/code&gt;'s constructor, sees it needs a &lt;code&gt;PaymentGateway&lt;/code&gt;, builds that first, then builds and caches the service. Dependency resolution, bottom-up construction, singleton caching: all there, in a dozen lines.&lt;/p&gt;

&lt;p&gt;Which raises the obvious question. If this little object already builds and wires beans, why does every real Spring application use something bigger?&lt;/p&gt;

&lt;h2&gt;
  
  
  What the bare factory quietly doesn't do
&lt;/h2&gt;

&lt;p&gt;Try feeding the bare factory a class written the way the previous articles taught:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@PostConstruct&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wired and ready"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register it, fetch it. No error. No warning. But &lt;code&gt;gateway&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;, and "wired and ready" never prints. Every annotation on that class was silently ignored.&lt;/p&gt;

&lt;p&gt;Here is why, and it connects straight back to the lifecycle article. Features like &lt;code&gt;@Autowired&lt;/code&gt;, &lt;code&gt;@PostConstruct&lt;/code&gt;, and the proxy that powers &lt;code&gt;@Transactional&lt;/code&gt; are not built into the factory core at all. Each one is implemented by a &lt;strong&gt;&lt;code&gt;BeanPostProcessor&lt;/code&gt;&lt;/strong&gt; — the lifecycle hook that gets a crack at every bean as it is built. Field injection is done by one post-processor. Init annotations by another. Proxy wrapping by a third. They are plugins around the factory, not parts of it.&lt;/p&gt;

&lt;p&gt;And the bare factory ships with &lt;strong&gt;none of them registered&lt;/strong&gt;. If you insist on using it raw, you have to install each plugin yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addBeanPostProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AutowiredAnnotationBeanPostProcessor&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// ...and one for @PostConstruct, one for @Transactional proxies, one for...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Forget one, and that feature simply doesn't exist in your application. Nothing fails loudly — fields just stay &lt;code&gt;null&lt;/code&gt;, transactions just don't open. A container that ignores your annotations &lt;em&gt;without telling you&lt;/em&gt; is a container you don't want to operate by hand. What you want is the version that comes fully staffed.&lt;/p&gt;

&lt;h2&gt;
  
  
  ApplicationContext: the factory, fully staffed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ApplicationContext&lt;/code&gt;&lt;/strong&gt; is an interface that &lt;em&gt;extends&lt;/em&gt; &lt;code&gt;BeanFactory&lt;/code&gt;. It is not a rival container — it is a superset, and the inheritance is written right in its declaration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ApplicationContext&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ListableBeanFactory&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;EnvironmentCapable&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MessageSource&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;ApplicationEventPublisher&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ResourcePatternResolver&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// every BeanFactory method, plus all of the above&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each parent interface in that list is a service a real application was going to need anyway:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ListableBeanFactory&lt;/code&gt;&lt;/strong&gt; — enumerate beans, not just look them up one at a time. This is the machinery behind injecting a &lt;code&gt;List&amp;lt;ShippingRule&amp;gt;&lt;/code&gt; of every implementation, the plugin trick from the DI article.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;EnvironmentCapable&lt;/code&gt;&lt;/strong&gt; — access to properties and profiles, which is what makes &lt;code&gt;@Value("${...}")&lt;/code&gt; resolve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ApplicationEventPublisher&lt;/code&gt;&lt;/strong&gt; — publish events to other beans (a concrete example in a moment).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;MessageSource&lt;/code&gt;&lt;/strong&gt; — translated text for internationalization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ResourcePatternResolver&lt;/code&gt;&lt;/strong&gt; — load files from the classpath or disk with one call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the bigger difference is behavioral. An &lt;code&gt;ApplicationContext&lt;/code&gt; &lt;strong&gt;registers all the standard post-processors automatically&lt;/strong&gt;. Create one and every annotation just works — injection, init callbacks, proxies, the lot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ApplicationContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.shop"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// gateway injected, @PostConstruct ran, proxies applied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The string is the package to scan: the context finds every &lt;code&gt;@Component&lt;/code&gt; under &lt;code&gt;com.shop&lt;/code&gt; and registers it, no manual &lt;code&gt;registerBeanDefinition&lt;/code&gt; needed. And it is the same &lt;code&gt;getBean&lt;/code&gt; call as before — it &lt;em&gt;is&lt;/em&gt; a &lt;code&gt;BeanFactory&lt;/code&gt;, after all. The difference is everything that already happened before you asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eager startup — the difference you can feel
&lt;/h2&gt;

&lt;p&gt;Remember that the bare factory is lazy: nothing is built until first asked for. The &lt;code&gt;ApplicationContext&lt;/code&gt; makes the opposite choice. During startup it walks every singleton definition and &lt;strong&gt;builds them all eagerly&lt;/strong&gt;, before the application serves a single request.&lt;/p&gt;

&lt;p&gt;That sounds like a detail. It is actually a guarantee about &lt;em&gt;when you find out something is broken&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;With a lazy container, a bean with a missing dependency or a broken constructor sits undetected until the first time someone asks for it — which might be a rarely-used endpoint, three days after deploy, in production, on a real user. With eager startup, that same mistake kills the application at boot, on your machine or in CI, with a stack trace pointing at the bad bean.&lt;/p&gt;

&lt;p&gt;This is the same fail-fast philosophy the DI article praised when constructor injection turned circular dependencies into boot-time errors. Failing at the safest possible moment is the feature. (When a bean is genuinely too expensive to build up front, &lt;code&gt;@Lazy&lt;/code&gt; opts it out one bean at a time — but the eager default is the right one.)&lt;/p&gt;

&lt;h2&gt;
  
  
  One of the extras, in action: events
&lt;/h2&gt;

&lt;p&gt;The added interfaces aren't decoration; they change how you can structure code. Take &lt;code&gt;ApplicationEventPublisher&lt;/code&gt;. Suppose that after an order is placed, an email should go out — but &lt;code&gt;OrderService&lt;/code&gt; shouldn't know or care about email. Publish a plain object as an &lt;strong&gt;event&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ApplicationEventPublisher&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ApplicationEventPublisher&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;placeOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...persist the order...&lt;/span&gt;
        &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publishEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderPlaced&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any other bean can listen for it by annotating a method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailNotifier&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@EventListener&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderPlaced&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// send the confirmation email&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container delivers the event from publisher to every listener. &lt;code&gt;OrderService&lt;/code&gt; gained an email feature without ever learning that email exists — and adding an SMS notifier later means adding one new bean, touching nothing. A bare &lt;code&gt;BeanFactory&lt;/code&gt; has no idea how to do any of this. The container as &lt;em&gt;event bus&lt;/em&gt; only exists at the &lt;code&gt;ApplicationContext&lt;/code&gt; level.&lt;/p&gt;

&lt;h2&gt;
  
  
  So which one do you use?
&lt;/h2&gt;

&lt;p&gt;In application code: always &lt;code&gt;ApplicationContext&lt;/code&gt;. In practice you never even construct it yourself: &lt;code&gt;SpringApplication.run(...)&lt;/code&gt; builds one and hands it back. Every Spring Boot app you have ever run was an &lt;code&gt;ApplicationContext&lt;/code&gt; the whole time.&lt;/p&gt;

&lt;p&gt;Under the hood, the relationship is composition, not reimplementation. A running &lt;code&gt;ApplicationContext&lt;/code&gt; holds a &lt;code&gt;DefaultListableBeanFactory&lt;/code&gt; &lt;em&gt;inside it&lt;/em&gt; and delegates every &lt;code&gt;getBean&lt;/code&gt; call down to it. The context is a shell of services wrapped around the same little factory you drove by hand earlier. That is why &lt;code&gt;BeanFactory&lt;/code&gt; still exists as a separate interface: it is the internal engine and the extension point framework code is written against. You will see the name in Spring's own internals and in stack traces — but app code has no reason to reach for it.&lt;/p&gt;

&lt;p&gt;One habit falls out of the layering. When a bean needs one of the context's services, inject the &lt;em&gt;narrow&lt;/em&gt; interface, not the whole context. The &lt;code&gt;OrderService&lt;/code&gt; above asked for &lt;code&gt;ApplicationEventPublisher&lt;/code&gt;, not &lt;code&gt;ApplicationContext&lt;/code&gt; — so its signature admits exactly what it uses, and a test can hand it a one-line fake instead of a whole container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;BeanFactory&lt;/code&gt; and &lt;code&gt;ApplicationContext&lt;/code&gt; are the same container at two levels of dress. &lt;strong&gt;&lt;code&gt;BeanFactory&lt;/code&gt;&lt;/strong&gt; is the minimal contract — store definitions, build beans lazily on request — and &lt;code&gt;DefaultListableBeanFactory&lt;/code&gt; is its real implementation, the engine at the bottom of every Spring app. &lt;strong&gt;&lt;code&gt;ApplicationContext&lt;/code&gt;&lt;/strong&gt; extends it and staffs it: all the standard post-processors registered automatically so annotations actually work, singletons built eagerly so broken wiring fails at boot instead of in production, plus events, properties, messages, and resources.&lt;/p&gt;

&lt;p&gt;The bare factory ignores your annotations silently; the context honors them automatically. That single difference decides the question for you: use the &lt;code&gt;ApplicationContext&lt;/code&gt;, let Boot create it, and remember that somewhere inside it, the little factory is still doing all the building.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Bean scopes (singleton/prototype/request/session) + singleton thread-safety gotcha</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Mon, 08 Jun 2026 07:41:11 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/bean-scopes-singletonprototyperequestsession-singleton-thread-safety-gotcha-10n</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/bean-scopes-singletonprototyperequestsession-singleton-thread-safety-gotcha-10n</guid>
      <description>&lt;p&gt;Every object the container builds has to answer two quiet questions: how many copies of it should exist, and how long should each one live? One shared copy for the whole application? A fresh one every time someone asks? One per web request? The answer to those two questions is the bean's &lt;strong&gt;scope&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You usually meet scope the day shared state misbehaves. A field on a &lt;code&gt;@Service&lt;/code&gt; holds a value for one user and somehow shows up for another. Or you expected a brand-new object each time and kept getting the same one back. Both are scope surprises — and both have the same root cause once you can see it.&lt;/p&gt;

&lt;p&gt;So this article walks the scopes Spring gives you, starting with the default you have been leaning on without ever naming it. Then it covers the two traps scope sets — including the one that causes real, hard-to-find production bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The default you have already been using
&lt;/h2&gt;

&lt;p&gt;Every bean in the previous articles was a &lt;strong&gt;singleton&lt;/strong&gt;: the container builds exactly one instance, caches it at startup, and hands that same object to everyone who needs it, for the whole life of the application. You never asked for this. It is simply what &lt;code&gt;@Component&lt;/code&gt;, &lt;code&gt;@Service&lt;/code&gt;, and a bare &lt;code&gt;@Bean&lt;/code&gt; give you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// one instance, shared everywhere&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ask the container for it twice and you get the identical object back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// a == b  → true, same instance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One word of caution on the name. A Spring &lt;strong&gt;singleton&lt;/strong&gt; means &lt;em&gt;one instance per container&lt;/em&gt; — not the classic JVM-wide singleton from design-pattern books. Spin up a second container and you get a second instance. Within one application that distinction rarely bites, but it is why "singleton" here is a scope, not a guarantee about the whole JVM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asking for a fresh one each time: prototype
&lt;/h2&gt;

&lt;p&gt;Sometimes one shared instance is exactly wrong. You want a short-lived, stateful helper — a builder you fill in, use once, and throw away. For that, Spring offers the &lt;strong&gt;prototype&lt;/strong&gt; scope: a brand-new instance every single time the bean is requested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="nd"&gt;@Scope&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"prototype"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReportBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// a new one on every request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now each &lt;code&gt;getBean&lt;/code&gt; hands back a different object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ReportBuilder&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ReportBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;ReportBuilder&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ReportBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// a != b  → two separate instances&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two more things change with prototype. The container builds it &lt;strong&gt;on demand&lt;/strong&gt;, when you ask — not eagerly at startup like a singleton. And, as the lifecycle article noted, Spring runs a prototype's setup but then forgets it: it never calls the destroy stage. The container builds a prototype, hands it over, and walks away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the default is a singleton — and the trap hiding inside it
&lt;/h2&gt;

&lt;p&gt;One shared instance is cheap and fast, which is why it is the default. But "shared" is the dangerous word, and it leads straight to the single most common Spring bug.&lt;/p&gt;

&lt;p&gt;A web application handles many requests at the same time, each on its own thread. Every one of those threads calls into the &lt;em&gt;same&lt;/em&gt; singleton instance. So any mutable field on a singleton is shared across all of them at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CartService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;itemCount&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// ONE field, shared by every thread&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;itemCount&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// two threads here = lost updates&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks fine in testing, where one request runs at a time. In production it corrupts data. Two users add items concurrently, both threads read &lt;code&gt;itemCount&lt;/code&gt;, both increment, both write back — and one update vanishes. Worse, one user's count is now visible to another, because there was only ever one field.&lt;/p&gt;

&lt;p&gt;The fix is a rule, not a trick: &lt;strong&gt;keep singletons stateless.&lt;/strong&gt; Don't store per-call or per-user data in fields. Let that data live in method parameters, local variables, and return values — those sit on each thread's own stack, so they are never shared.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CartService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;withItemAdded&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// state passed in and out, never stored&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note what is &lt;em&gt;not&lt;/em&gt; a problem: fields that are set once at construction and never change — your injected dependencies, anything &lt;code&gt;final&lt;/code&gt;. Those are shared too, but since nobody mutates them, no thread can corrupt them. The bug is specifically &lt;em&gt;mutable&lt;/em&gt; shared state. Immutable shared state is exactly what a singleton is good at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scopes that follow the web request
&lt;/h2&gt;

&lt;p&gt;Sometimes you genuinely need per-user or per-request state, and stuffing it through method parameters everywhere gets ugly. For that, Spring adds two web-aware scopes.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;request-scoped&lt;/strong&gt; bean lives for exactly one HTTP request: the container builds a fresh one when the request arrives and discards it when the response is sent. A &lt;strong&gt;session-scoped&lt;/strong&gt; bean lives for one user's session, spanning their many requests until the session ends.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="nd"&gt;@RequestScope&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RequestContext&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;traceId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// safe: each request gets its own instance&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because every request gets its own instance, that mutable &lt;code&gt;traceId&lt;/code&gt; field is now perfectly safe — the sharing that doomed the singleton simply isn't there. This is the right home for "data that belongs to this one request."&lt;/p&gt;

&lt;p&gt;But it raises an awkward question. A singleton is built once, at startup. A request-scoped bean does not exist yet at startup — no request is in flight. So how can you inject a request-scoped bean into a singleton, when the thing you want to inject won't exist until much later, and then keeps being replaced?&lt;/p&gt;

&lt;h2&gt;
  
  
  The scoped-proxy fix
&lt;/h2&gt;

&lt;p&gt;This is where the &lt;strong&gt;proxy&lt;/strong&gt; from the first article comes back to do real work. When you inject a shorter-lived bean into a longer-lived one, Spring does not inject the real bean — it injects a &lt;strong&gt;proxy&lt;/strong&gt;: a same-shaped stand-in that, on every method call, looks up the correct instance for the &lt;em&gt;current&lt;/em&gt; request and forwards to it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@RequestScope&lt;/code&gt; switches this proxy on by default, so the injection just works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuditService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RequestContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// really a proxy, injected once&lt;/span&gt;

    &lt;span class="nc"&gt;AuditService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RequestContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;record&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTraceId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// resolves to THIS request's instance&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The singleton &lt;code&gt;AuditService&lt;/code&gt; is wired exactly once at startup, holding the proxy forever. But each call through that proxy lands on the right per-request &lt;code&gt;RequestContext&lt;/code&gt;. Without the proxy you would be stuck: either a startup failure because no request exists to inject, or one shared instance that defeats the entire point of request scope. The proxy bridges the lifespans.&lt;/p&gt;

&lt;h2&gt;
  
  
  The prototype-in-singleton trap
&lt;/h2&gt;

&lt;p&gt;Now the trap that catches almost everyone, because it fails silently rather than loudly. Inject a prototype into a singleton the obvious way, and you do &lt;em&gt;not&lt;/em&gt; get a fresh prototype per call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ReportBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// injected ONCE, frozen forever&lt;/span&gt;

    &lt;span class="nc"&gt;InvoiceService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ReportBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reset&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// same instance every invoice — not what you wanted&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You chose &lt;code&gt;prototype&lt;/code&gt; precisely so each invoice would get its own &lt;code&gt;ReportBuilder&lt;/code&gt;. Instead you got exactly one, captured at startup, reused for the life of the app. The reason is simple once it clicks: &lt;strong&gt;injection is a one-time event for a singleton.&lt;/strong&gt; Spring builds &lt;code&gt;InvoiceService&lt;/code&gt; once, so it resolves and injects its dependencies once. The prototype scope only promises a new instance &lt;em&gt;per request to the container&lt;/em&gt; — and that request happened a single time, at wiring.&lt;/p&gt;

&lt;p&gt;The fix is to ask the container for a new one at the moment you need it, instead of capturing one at startup. &lt;code&gt;ObjectProvider&lt;/code&gt; is the clean way to do exactly that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ObjectProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReportBuilder&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;builders&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InvoiceService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ObjectProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReportBuilder&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;builders&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builders&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ReportBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getObject&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// a fresh prototype each call&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;getObject()&lt;/code&gt; is a new request to the container, so each returns a new prototype. (A scoped proxy on the prototype achieves the same thing transparently, the way &lt;code&gt;@RequestScope&lt;/code&gt; did — but &lt;code&gt;ObjectProvider&lt;/code&gt; makes the "give me a fresh one now" intent obvious at the call site.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;A scope answers two questions about a bean: &lt;strong&gt;how many&lt;/strong&gt; instances exist, and &lt;strong&gt;how long&lt;/strong&gt; each lives. &lt;strong&gt;Singleton&lt;/strong&gt; — one per container, the default — is built once and shared by everyone. &lt;strong&gt;Prototype&lt;/strong&gt; is a new instance on every request, built on demand, and never destroyed by the container. &lt;strong&gt;Request&lt;/strong&gt; and &lt;strong&gt;session&lt;/strong&gt; scope tie a bean's life to one HTTP request or one user's session.&lt;/p&gt;

&lt;p&gt;Both traps in this article come from mixing lifespans. The thread-safety bug is one singleton shared across many threads at once, so any mutable field is a race — fixed by keeping singletons stateless. The stale-injection bug is a short-lived bean injected once into a long-lived one, so it freezes at startup — fixed by the scoped proxy, or by pulling a fresh instance from an &lt;code&gt;ObjectProvider&lt;/code&gt; when you actually need it.&lt;/p&gt;

&lt;p&gt;Hold on to the one idea underneath both: for a singleton, wiring happens exactly once. Everything that surprises you about scope follows from remembering when injection actually runs.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Bean lifecycle: instantiate populate init destroy</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Mon, 08 Jun 2026 06:49:43 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/bean-lifecycle-instantiate-populate-init-destroy-2p68</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/bean-lifecycle-instantiate-populate-init-destroy-2p68</guid>
      <description>&lt;p&gt;A Spring bean does not blink into existence fully formed. The container assembles it in a fixed order of stages — build the object, fill in its dependencies, run its setup, and much later, run its teardown. That ordered sequence is the &lt;strong&gt;bean lifecycle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You meet it the first time you need something to happen at an exact moment. You want a connection pool opened &lt;em&gt;after&lt;/em&gt; the bean has all its dependencies, but &lt;em&gt;before&lt;/em&gt; it handles a single request. You want a cache flushed to disk when the app shuts down — but only if startup actually finished. To put your code in the right place, you have to know the order these stages run in, and what is guaranteed to be ready when each one fires.&lt;/p&gt;

&lt;p&gt;The whole lifecycle is just the container doing work around an object it built. We will walk it end to end: the four main stages, the hooks Spring opens at each one, and two traps that fall straight out of the ordering.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four stages, in one breath
&lt;/h2&gt;

&lt;p&gt;Here is the spine of the whole article — the path every singleton bean walks, from startup to shutdown:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instantiate&lt;/strong&gt; — construct the raw object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Populate&lt;/strong&gt; — inject its dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initialize&lt;/strong&gt; — run setup now that it is fully wired.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destroy&lt;/strong&gt; — run teardown at shutdown.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything else is detail hung on those four pegs. Let's take them one at a time, because the &lt;em&gt;order&lt;/em&gt; is the entire point — each stage is only safe to use once you know what ran before it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 1: instantiate — a bare object
&lt;/h2&gt;

&lt;p&gt;First the container calls a constructor and gets back a raw Java object. Nothing Spring-specific has happened yet; this is the same &lt;code&gt;new&lt;/code&gt; you would write by hand, just done for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InventoryService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;WarehouseClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InventoryService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WarehouseClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// constructor injection&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a subtlety worth pausing on. When you use &lt;strong&gt;constructor injection&lt;/strong&gt; — dependencies passed as constructor arguments, as above — the wiring happens &lt;em&gt;inside&lt;/em&gt; this first stage. Spring works out what &lt;code&gt;WarehouseClient&lt;/code&gt; is, builds it, and hands it in as the object is created. For constructor-injected beans, "instantiate" and "populate" are the same moment.&lt;/p&gt;

&lt;p&gt;That is &lt;em&gt;not&lt;/em&gt; true for the other injection styles, and the difference is where the next stage earns its name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2: populate — the fields get filled
&lt;/h2&gt;

&lt;p&gt;If a dependency is injected into a field or through a setter, it cannot arrive in the constructor — the object has to exist first, then Spring reaches in and sets it. That second step is &lt;strong&gt;populate&lt;/strong&gt;: the container assigns every field- and setter-injected dependency onto the freshly built object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InventoryService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WarehouseClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// set during populate, not in the constructor&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ordering explains a bug everyone hits once. A field-injected dependency is &lt;code&gt;null&lt;/code&gt; if you touch it inside the constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InventoryService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WarehouseClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InventoryService&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// NullPointerException — populate hasn't run yet&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The constructor runs in stage 1. Populate is stage 2. At the moment the constructor body executes, the field is still empty. This is one more reason the previous article pushed constructor injection so hard: it collapses these two stages into one, so a dependency is never half-there. But when you do use field or setter injection, populate is the stage that fills them — and nothing before it can rely on them.&lt;/p&gt;

&lt;p&gt;Between populate and the next stage, Spring may also hand the bean a few references to the container itself, if the bean asks for them by implementing an &lt;strong&gt;Aware&lt;/strong&gt; interface (for example &lt;code&gt;BeanNameAware&lt;/code&gt; to learn its own bean name). It is a narrow feature you will rarely reach for, but it slots in right here: after the dependencies, before initialization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 3: initialize — the bean gets ready
&lt;/h2&gt;

&lt;p&gt;Now the object is fully wired. This is the moment to do setup that &lt;em&gt;needs&lt;/em&gt; the dependencies in place — open that connection pool, warm a cache, validate configuration. Spring calls this the &lt;strong&gt;initialization&lt;/strong&gt; stage, and it gives you a hook that fires exactly here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InventoryService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;WarehouseClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InventoryService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WarehouseClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@PostConstruct&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;openPool&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// every dependency is guaranteed wired by now&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;@PostConstruct&lt;/code&gt; method runs after populate, so it can lean on every dependency being present — the guarantee the constructor could not give you. This is the &lt;em&gt;right&lt;/em&gt; home for "do this once, at startup, after wiring."&lt;/p&gt;

&lt;p&gt;There are three ways to register init code, and when more than one is present they run in a fixed order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A method annotated &lt;strong&gt;&lt;code&gt;@PostConstruct&lt;/code&gt;&lt;/strong&gt; — runs first. This is the standard, framework-agnostic choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;afterPropertiesSet()&lt;/code&gt;&lt;/strong&gt;, if the bean implements the &lt;code&gt;InitializingBean&lt;/code&gt; interface — runs second. It couples your class to Spring's API, so it is rarely the better option.&lt;/li&gt;
&lt;li&gt;A method named in &lt;strong&gt;&lt;code&gt;@Bean(initMethod = "...")&lt;/code&gt;&lt;/strong&gt; — runs last. Useful when the class is third-party and you cannot annotate it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reach for &lt;code&gt;@PostConstruct&lt;/code&gt; unless you have a specific reason not to. The other two exist mostly for cases where you cannot put an annotation on the method.&lt;/p&gt;

&lt;h2&gt;
  
  
  The proxy slips in right after init
&lt;/h2&gt;

&lt;p&gt;Remember from the first article that the container can wrap a bean in a &lt;strong&gt;proxy&lt;/strong&gt; — a same-shaped stand-in that runs extra code (a transaction, an async hand-off) around your methods. The lifecycle is where that wrapping actually happens, and &lt;em&gt;exactly when&lt;/em&gt; it happens is the source of a classic trap.&lt;/p&gt;

&lt;p&gt;Spring exposes the init stage through an interface called &lt;strong&gt;&lt;code&gt;BeanPostProcessor&lt;/code&gt;&lt;/strong&gt;, which has two callbacks: one that runs &lt;em&gt;before&lt;/em&gt; your init code, and one that runs &lt;em&gt;after&lt;/em&gt;. The proxy is created in that second, after-init callback. So the order is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Populate the bean.&lt;/li&gt;
&lt;li&gt;Run your &lt;code&gt;@PostConstruct&lt;/code&gt; / init methods — on the &lt;strong&gt;raw&lt;/strong&gt; object.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Then&lt;/em&gt; wrap the result in a proxy and store that proxy in the container.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read step 2 again, because it bites. Inside &lt;code&gt;@PostConstruct&lt;/code&gt;, the proxy does not exist yet. The &lt;code&gt;this&lt;/code&gt; you are holding is the bare bean. So if your init method calls one of its own proxied methods, the wrapper is skipped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@PostConstruct&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;warmUp&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reload&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// if reload() is @Transactional, there is NO transaction here&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;reload()&lt;/code&gt; may be annotated &lt;code&gt;@Transactional&lt;/code&gt;, but calling it through &lt;code&gt;this&lt;/code&gt; during init goes straight to the raw method — the proxy that would have opened the transaction has not been built yet. The fix is not to depend on proxied behavior from inside initialization. The lesson generalizes: &lt;strong&gt;your own init code always sees the unwrapped bean.&lt;/strong&gt; Everyone else, fetching the bean from the container later, sees the proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  In service
&lt;/h2&gt;

&lt;p&gt;Once initialization and any wrapping are done, the bean is finished. The container drops it on the shelf and hands out that same instance — the proxy, if there is one — to everyone who needs it, for the rest of the application's life. No more lifecycle events fire until shutdown. For a normal singleton, that "in service" period is essentially the whole life of the program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 4: destroy — teardown at shutdown
&lt;/h2&gt;

&lt;p&gt;When the application context closes — a graceful shutdown, a &lt;code&gt;SIGTERM&lt;/code&gt;, the JVM shutdown hook firing — Spring walks its singletons one last time and runs their teardown. This is the place to release what initialization acquired: close the pool, flush the buffer, deregister from a discovery service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@PreDestroy&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;closePool&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// mirror of @PostConstruct, run on the way down&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Destruction mirrors initialization exactly, including the three-way ordering:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A method annotated &lt;strong&gt;&lt;code&gt;@PreDestroy&lt;/code&gt;&lt;/strong&gt; — runs first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;destroy()&lt;/code&gt;&lt;/strong&gt;, if the bean implements &lt;code&gt;DisposableBean&lt;/code&gt; — runs second.&lt;/li&gt;
&lt;li&gt;A method named in &lt;strong&gt;&lt;code&gt;@Bean(destroyMethod = "...")&lt;/code&gt;&lt;/strong&gt; — runs last.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One honest caveat: these run only on an &lt;em&gt;orderly&lt;/em&gt; shutdown, when Spring is given the chance to close the context. A hard kill — &lt;code&gt;kill -9&lt;/code&gt;, a power loss — bypasses the whole stage. So &lt;code&gt;@PreDestroy&lt;/code&gt; is the right place for a graceful flush, but it is not a guarantee that your teardown will ever run. Anything that absolutely must survive a crash needs to be durable by other means, not parked in a destroy callback.&lt;/p&gt;

&lt;h2&gt;
  
  
  The prototype trap
&lt;/h2&gt;

&lt;p&gt;Everything above describes a &lt;strong&gt;singleton&lt;/strong&gt; — the default, one shared instance the container holds and manages. Spring also offers the &lt;strong&gt;prototype&lt;/strong&gt; scope, where you get a brand-new bean every time you ask for one. Prototypes go through the first three stages in full: Spring instantiates them, populates them, and runs their init callbacks.&lt;/p&gt;

&lt;p&gt;Then it lets go. &lt;strong&gt;Spring does not run the destroy stage for prototype beans.&lt;/strong&gt; It builds one, hands it to you, and forgets it ever existed — so &lt;code&gt;@PreDestroy&lt;/code&gt; on a prototype is never called by the container.&lt;/p&gt;

&lt;p&gt;That is a real leak waiting to happen. If a prototype opens a file handle or a socket in &lt;code&gt;@PostConstruct&lt;/code&gt;, expecting &lt;code&gt;@PreDestroy&lt;/code&gt; to close it, the close never fires and the resource leaks every time you request the bean. For a prototype that holds something which must be released, you are responsible for closing it yourself — the lifecycle only takes you halfway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;A bean is built in four ordered stages, and the order is the whole point. &lt;strong&gt;Instantiate&lt;/strong&gt; makes the raw object — and for constructor injection, wires it at the same time. &lt;strong&gt;Populate&lt;/strong&gt; fills in any field- and setter-injected dependencies, which is why those are &lt;code&gt;null&lt;/code&gt; if you touch them too early. &lt;strong&gt;Initialize&lt;/strong&gt; runs your setup once everything is wired, with &lt;code&gt;@PostConstruct&lt;/code&gt; as the natural home. And &lt;strong&gt;destroy&lt;/strong&gt; runs your teardown on an orderly shutdown, with &lt;code&gt;@PreDestroy&lt;/code&gt; as its mirror.&lt;/p&gt;

&lt;p&gt;Two traps fall straight out of that ordering. The proxy is built &lt;em&gt;after&lt;/em&gt; your init code, so initialization always sees the unwrapped bean — self-calls to transactional or async methods quietly do nothing there. And prototypes get the first three stages but never the fourth, so anything they open, you must close.&lt;/p&gt;

&lt;p&gt;Hold on to the shape rather than the annotations: wired, then ready, then — much later, and only if you shut down cleanly — gone.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Dependency Injection — the problem it solves</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Mon, 08 Jun 2026 06:43:53 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/dependency-injection-the-problem-it-solves-5098</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/dependency-injection-the-problem-it-solves-5098</guid>
      <description>&lt;p&gt;The first article in this module made one claim and moved on: stop calling &lt;code&gt;new&lt;/code&gt; on your collaborators, and let the container hand them in. That was the &lt;em&gt;what&lt;/em&gt;. This article is the &lt;em&gt;why&lt;/em&gt; — because a rule you don't understand is a rule you'll break the first time it's inconvenient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency injection&lt;/strong&gt; is the practice of giving an object the things it needs from the outside, instead of letting it build them itself. You met the name in passing already. Here we look at what it actually buys you, what it costs, and why one way of doing it is plainly better than the rest.&lt;/p&gt;

&lt;p&gt;You hit this decision every time you write a class that needs another class. Do you reach for &lt;code&gt;new&lt;/code&gt; and build the collaborator inside? Or do you ask for it and let something else supply it? That one choice, repeated across a codebase, is the difference between code you can test and change and code that quietly fights you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing DI actually fights
&lt;/h2&gt;

&lt;p&gt;It is tempting to think the enemy here is the &lt;code&gt;new&lt;/code&gt; keyword. It isn't. The enemy is &lt;strong&gt;coupling to construction&lt;/strong&gt; — a class deciding, inside its own body, exactly how its collaborators are built.&lt;/p&gt;

&lt;p&gt;Look at what a class signs up for the moment it builds its own collaborator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StripeClient&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;placeOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one line welds together two decisions that have nothing to do with each other:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt; &lt;code&gt;OrderService&lt;/code&gt; needs — something that can charge money.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which&lt;/strong&gt; exact thing it gets, and how that thing is built — this concrete class, wired to Stripe, constructed just so.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first decision is &lt;code&gt;OrderService&lt;/code&gt;'s business. The second is not. &lt;code&gt;OrderService&lt;/code&gt; should not hold an opinion on whether payments go through Stripe or Adyen, or what a gateway needs underneath. The moment it bakes that opinion into code, the two decisions can never move apart again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pulling the two decisions apart
&lt;/h2&gt;

&lt;p&gt;So separate them. Make &lt;code&gt;OrderService&lt;/code&gt; depend only on the &lt;em&gt;role&lt;/em&gt; — what it needs — and let it state that need without naming a concrete class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// "give me something that charges"&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; now names an interface and nothing else. It has no idea which class shows up at runtime. Something outside decides that and supplies it.&lt;/p&gt;

&lt;p&gt;The principle you just applied has a name: &lt;strong&gt;depend on abstractions, not on concrete implementations&lt;/strong&gt; — and let an outside party choose and supply the concrete one. Dependency injection is simply the delivery mechanism for that idea. The interface is the contract; injection is how the chosen implementation arrives.&lt;/p&gt;

&lt;p&gt;That separation is the whole payoff, and it shows up in three concrete ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can test it.&lt;/strong&gt; In a test you hand &lt;code&gt;OrderService&lt;/code&gt; a fake gateway that records calls instead of hitting a bank — possible only because nothing concrete is baked in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can swap implementations.&lt;/strong&gt; Moving from Stripe to Adyen in production means changing one bean definition. Not a single line of &lt;code&gt;OrderService&lt;/code&gt; changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The container can wrap what it supplies.&lt;/strong&gt; Because the gateway arrives from outside, the container gets a chance to hand you something that isn't your plain object — it can wrap it first. That wrap is how &lt;code&gt;@Transactional&lt;/code&gt; and the other annotations from the last article attach themselves, and it is only possible because you didn't build the thing yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Spring picks what to inject
&lt;/h2&gt;

&lt;p&gt;So &lt;code&gt;OrderService&lt;/code&gt; asks for a &lt;code&gt;PaymentGateway&lt;/code&gt;. How does the container know what to give it?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By type.&lt;/strong&gt; When Spring builds &lt;code&gt;OrderService&lt;/code&gt; and sees a constructor parameter of type &lt;code&gt;PaymentGateway&lt;/code&gt;, it looks through the beans it knows about for one whose type fits &lt;code&gt;PaymentGateway&lt;/code&gt;, and injects that one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeGateway&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You never told Spring "use &lt;code&gt;StripeGateway&lt;/code&gt; for &lt;code&gt;OrderService&lt;/code&gt;." You declared a need by type, you have one bean of that type, and the container connected them.&lt;/p&gt;

&lt;p&gt;What happens when &lt;em&gt;two&lt;/em&gt; classes implement &lt;code&gt;PaymentGateway&lt;/code&gt; — how you break the tie — is its own topic later in this module. For now the point is just this: resolution is by type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the style of injection is not a matter of taste
&lt;/h2&gt;

&lt;p&gt;There are three places Spring can put an injected dependency: the constructor, a setter, or straight into a field by reflection. They look interchangeable. They are not — and the difference is mechanical, not stylistic.&lt;/p&gt;

&lt;p&gt;Here is the field version. It looks the cleanest and costs the most:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// looks tidy&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch what this quietly allows. The object can be &lt;strong&gt;fully built while completely empty&lt;/strong&gt; — &lt;code&gt;new OrderService()&lt;/code&gt; succeeds and hands you an instance whose &lt;code&gt;gateway&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;. The field can't be &lt;code&gt;final&lt;/code&gt;, so it stays mutable for the object's whole life. The only way to fill it is reflection, so you can't build a valid instance in a plain unit test without dragging Spring in. And the dependency is invisible from outside: nothing in the signature tells a caller this class even needs a gateway.&lt;/p&gt;

&lt;p&gt;Now the constructor version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every one of those problems is gone — and not by convention, by language mechanics. The field is &lt;code&gt;final&lt;/code&gt;, so it is set exactly once and the object is immutable after construction. There is &lt;strong&gt;no way to create the object without supplying its dependency&lt;/strong&gt;; the compiler enforces it. And the dependency is right there in the signature for anyone to read.&lt;/p&gt;

&lt;p&gt;The testing win becomes concrete the moment you write a test. No framework, no reflection — just a constructor call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;chargesTheOrderTotal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RecordingGateway&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// a fake, records instead of charging&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// plain Java, no Spring in sight&lt;/span&gt;

    &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;placeOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;

    &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastCharge&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last point hides the most useful one. Because every dependency has to pass through the constructor, a class with too many of them grows an ugly seven-argument constructor you can't ignore. Field injection lets the same class quietly pile up fifteen &lt;code&gt;@Autowired&lt;/code&gt; fields and still look tidy. The constructor turns "this class is doing too much" from a hidden fact into a visible smell. That isn't a style preference — it is design feedback you would otherwise never get.&lt;/p&gt;

&lt;h2&gt;
  
  
  The circular-dependency trap
&lt;/h2&gt;

&lt;p&gt;There is a sharper version of the same benefit, and it is worth seeing in full. Suppose &lt;code&gt;A&lt;/code&gt; needs &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;B&lt;/code&gt; needs &lt;code&gt;A&lt;/code&gt; — a circular dependency.&lt;/p&gt;

&lt;p&gt;With field injection, Spring can often paper over it. It creates both raw objects first, then sets the fields afterward, so the cycle "works" by accident and ships. With constructor injection, neither object can be built before the other exists, so Spring can't even start — it fails at boot with &lt;code&gt;BeanCurrentlyInCreationException&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is tempting to read that as constructor injection being stricter and therefore more annoying. It is the opposite. The cycle is a real design flaw. Constructor injection forces you to see it the second you boot the app, instead of meeting it as a &lt;code&gt;StackOverflowError&lt;/code&gt; in production weeks later. Failing fast, at the safest possible moment, is the feature.&lt;/p&gt;

&lt;p&gt;Setter injection is the third style. It has one honest, narrow use: a genuinely &lt;em&gt;optional&lt;/em&gt; dependency that can be reconfigured after the object exists. That is rare. Everywhere else, reach for the constructor.&lt;/p&gt;

&lt;h2&gt;
  
  
  One thing resolution-by-type gives you for free
&lt;/h2&gt;

&lt;p&gt;Because injection is by type, a trick falls out that turns DI into a plugin system. Ask for a &lt;code&gt;List&lt;/code&gt; of an interface, and Spring injects &lt;strong&gt;every&lt;/strong&gt; bean that implements it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ShippingRule&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;applies&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="nf"&gt;surcharge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShippingCalculator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ShippingRule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;ShippingCalculator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ShippingRule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// every ShippingRule bean, injected&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="nf"&gt;totalSurcharge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;applies&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;surcharge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reduce&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ZERO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;Money:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding a new rule is now just adding one &lt;code&gt;@Component&lt;/code&gt; that implements &lt;code&gt;ShippingRule&lt;/code&gt;. &lt;code&gt;ShippingCalculator&lt;/code&gt; never changes — it doesn't even know how many rules exist. That is the plugin pattern, delivered entirely by DI.&lt;/p&gt;

&lt;p&gt;One trap rides along with it: &lt;strong&gt;the order of the beans in that injected list is not guaranteed&lt;/strong&gt; unless you make it so. If your rules must run in a set sequence — a discount rule before a tax rule — relying on whatever order Spring happened to hand them in is a bug waiting for the day a refactor reshuffles them. Pin it with &lt;code&gt;@Order&lt;/code&gt; on each implementation (or have them implement &lt;code&gt;Ordered&lt;/code&gt;), and the list arrives in that order. (Ask for &lt;code&gt;Map&amp;lt;String, ShippingRule&amp;gt;&lt;/code&gt; instead, and you get each implementation keyed by its bean name — handy when you need to pick one by name at runtime.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;Dependency injection isn't about dodging a keyword. It is about refusing to let a class decide both &lt;em&gt;what it needs&lt;/em&gt; and &lt;em&gt;which implementation it gets&lt;/em&gt; — and pulling those apart so the implementation can be swapped, centralized, and wrapped by the container.&lt;/p&gt;

&lt;p&gt;Spring resolves the need by type. Constructor injection is the way to receive it — not for neatness, but because the language then guarantees your object is immutable, impossible to build half-wired, trivial to test without the framework, and honest about how many dependencies it really carries. And once injection is by type, the &lt;code&gt;List&lt;/code&gt;-of-interface plugin pattern comes for free — just remember to pin the order when it matters.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Spring exists; the IoC container in one analogy</title>
      <dc:creator>Ankit Verma</dc:creator>
      <pubDate>Mon, 08 Jun 2026 06:41:13 +0000</pubDate>
      <link>https://dev.to/ankit_verma_e2fa7fb2aa95d/why-spring-exists-the-ioc-container-in-one-analogy-53n2</link>
      <guid>https://dev.to/ankit_verma_e2fa7fb2aa95d/why-spring-exists-the-ioc-container-in-one-analogy-53n2</guid>
      <description>&lt;p&gt;Spring is a framework that builds and connects the objects your application is made of. You write the classes. Spring creates them, wires them together, and hands them to each other at startup. That sounds like a small favor. It quietly reshapes how the whole codebase fits together, and almost every other Spring feature is built on top of it.&lt;/p&gt;

&lt;p&gt;You meet this on day one, usually before anyone names it for you. You open a Spring project, find a class with no &lt;code&gt;new&lt;/code&gt; anywhere in it, and wonder where its dependencies actually come from. The answer is the mechanism this article is about.&lt;/p&gt;

&lt;p&gt;So this first piece is about &lt;em&gt;why&lt;/em&gt; that job needs to exist at all, and the single mechanism Spring uses to do it. Once that mechanism is clear, most of Spring stops looking like magic.&lt;/p&gt;

&lt;p&gt;Let's start with no Spring at all, and watch the problem show up on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  A class that builds its own tools
&lt;/h2&gt;

&lt;p&gt;Here is a class that needs another class to do its job. The natural instinct is to build what it needs, right where it needs it, with &lt;code&gt;new&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpClient&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;placeOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at what &lt;code&gt;OrderService&lt;/code&gt; now owns. It places orders — that is its real job. But it also knows how to &lt;em&gt;build&lt;/em&gt; a &lt;code&gt;PaymentGateway&lt;/code&gt;. And because a gateway needs an &lt;code&gt;HttpClient&lt;/code&gt;, it builds that too. One class doing two jobs: its actual work, and the plumbing underneath it.&lt;/p&gt;

&lt;p&gt;That second job is where the trouble starts. It costs you three concrete things, and each one points to what comes next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can't test it in isolation.&lt;/strong&gt; The real &lt;code&gt;PaymentGateway&lt;/code&gt; calls a real bank. It is baked in with &lt;code&gt;new&lt;/code&gt;, so there is no way to slip a fake one in for a test. To test the order logic, you'd have to charge actual money.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The plumbing gets copied everywhere.&lt;/strong&gt; Every class that needs a gateway writes the same &lt;code&gt;new PaymentGateway(new HttpClient())&lt;/code&gt;. Change how a gateway is built, and you have to hunt down every copy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is nowhere to add shared behavior.&lt;/strong&gt; Suppose you want every payment wrapped in a database transaction. With the gateway hard-wired by &lt;code&gt;new&lt;/code&gt;, there is no single seam to hook that in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handing over control
&lt;/h2&gt;

&lt;p&gt;Now the same class, written the way Spring wants it. It stops building anything. It just states what it needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGateway&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;   &lt;span class="c1"&gt;// "I need a PaymentGateway"&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// someone hands one in&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; no longer knows or cares &lt;em&gt;how&lt;/em&gt; a &lt;code&gt;PaymentGateway&lt;/code&gt; is built. It declares the need in its constructor and trusts that a finished one will arrive from outside.&lt;/p&gt;

&lt;p&gt;That flip has a name. Normally your code is in control of creating its own collaborators. Here, your code gives that control away — something else creates the objects and supplies them. Handing that control to the framework is called &lt;strong&gt;Inversion of Control&lt;/strong&gt;, or IoC. The "control" is specifically control over creating and wiring objects. The "inversion" is that it now runs the other way around: the framework builds your objects and calls into them, instead of your objects building everything themselves.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;way&lt;/em&gt; the gateway actually arrives — through the constructor above — has its own name: &lt;strong&gt;Dependency Injection&lt;/strong&gt;, or DI. The dependency, the gateway, is injected into &lt;code&gt;OrderService&lt;/code&gt; from outside. It can arrive through a constructor, through a setter, or straight into a field. Prefer the constructor: the dependency is visible right there in the signature, and the field can be &lt;code&gt;final&lt;/code&gt;, so the object is complete the moment it exists.&lt;/p&gt;

&lt;p&gt;So IoC is the idea — your code no longer creates its own collaborators. DI is the delivery — how each collaborator gets in. Which raises the obvious question: who actually does the creating and the handing-over?&lt;/p&gt;

&lt;h2&gt;
  
  
  The container: a factory that runs at startup
&lt;/h2&gt;

&lt;p&gt;The thing that creates and wires your objects is the &lt;strong&gt;container&lt;/strong&gt;. In Spring it is an object called the &lt;code&gt;ApplicationContext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the one analogy worth holding onto: the container is a &lt;strong&gt;factory&lt;/strong&gt;. Not "factory" in the design-pattern sense — picture a literal assembly line that runs once, when your application starts. You hand it a list of what to build and how the pieces fit together. It produces every finished, connected object your app is made of, sets them on a shelf, and hands them out on request for the rest of the program's life. Everything below is just detail about how that factory runs.&lt;/p&gt;

&lt;p&gt;Two small words have been quietly working and now deserve a definition. To &lt;strong&gt;wire&lt;/strong&gt; two objects is just to give one a reference to the other — to set &lt;code&gt;OrderService&lt;/code&gt;'s &lt;code&gt;gateway&lt;/code&gt; field to a real &lt;code&gt;PaymentGateway&lt;/code&gt; instance, so the call inside &lt;code&gt;placeOrder&lt;/code&gt; has something to land on. And a &lt;strong&gt;bean&lt;/strong&gt; is simply an object that the factory creates and manages for you. Your &lt;code&gt;@Service&lt;/code&gt;, your &lt;code&gt;@Component&lt;/code&gt;, the things Spring builds — those are beans. An object you build yourself with &lt;code&gt;new&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a bean, because Spring never touched it. That distinction looks small now; it matters in a minute.&lt;/p&gt;

&lt;p&gt;Here is what the factory does, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It scans your code and writes down recipes, not objects.&lt;/strong&gt; When Spring sees &lt;code&gt;@Component&lt;/code&gt;, &lt;code&gt;@Service&lt;/code&gt;, or a method marked &lt;code&gt;@Bean&lt;/code&gt;, it does not build anything yet. It records a &lt;strong&gt;bean definition&lt;/strong&gt;: which class, how many copies to make, what that bean depends on, and any startup hooks. Think of it as a recipe card, not the finished dish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works out the dependency graph.&lt;/strong&gt; From those recipes it figures out who needs whom. &lt;code&gt;OrderService&lt;/code&gt; needs &lt;code&gt;PaymentGateway&lt;/code&gt;, which needs &lt;code&gt;HttpClient&lt;/code&gt;. A short chain here; in a real app, a wide web.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It builds the objects bottom-up.&lt;/strong&gt; You can't inject a &lt;code&gt;PaymentGateway&lt;/code&gt; before it exists, so Spring builds the leaves of the graph first and works upward, passing each finished bean into the next one's constructor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It caches each finished bean and reuses it.&lt;/strong&gt; Once a bean is built, the container keeps it and hands out that same instance to everyone who needs it. It does not build a fresh one each time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That third step is worth making concrete, because the &lt;em&gt;order&lt;/em&gt; is the whole point. Take the chain from earlier: &lt;code&gt;OrderService&lt;/code&gt; needs a &lt;code&gt;PaymentGateway&lt;/code&gt;, which needs an &lt;code&gt;HttpClient&lt;/code&gt;. The factory cannot build &lt;code&gt;OrderService&lt;/code&gt; first — it has nothing to put in the constructor yet. So it walks the chain from the bottom:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build &lt;code&gt;HttpClient&lt;/code&gt;. It depends on nothing, so it is a leaf and goes first.&lt;/li&gt;
&lt;li&gt;Build &lt;code&gt;PaymentGateway&lt;/code&gt;, passing in the &lt;code&gt;HttpClient&lt;/code&gt; from step 1.&lt;/li&gt;
&lt;li&gt;Build &lt;code&gt;OrderService&lt;/code&gt;, passing in the &lt;code&gt;PaymentGateway&lt;/code&gt; from step 2.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Three objects, built in the one order that lets each constructor receive a finished dependency. You never wrote a line of that sequencing. The factory read it off the graph and did it for you — and the same logic scales from this three-link chain to a graph with thousands of beans.&lt;/p&gt;

&lt;p&gt;By the time startup finishes, every bean exists and every dependency is in place. Asking for one is now instant, because the work already happened:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ApplicationContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// already built and wired&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The extra move: wrapping a bean in a proxy
&lt;/h2&gt;

&lt;p&gt;There is one more thing the factory can do while it builds a bean, and it explains a surprising amount of Spring. While assembling a bean, the container can wrap it in a &lt;strong&gt;proxy&lt;/strong&gt; before handing it over.&lt;/p&gt;

&lt;p&gt;A proxy is a stand-in object. It looks exactly like your bean — same type, same methods — but it runs a little extra code before and after each call, then forwards to your real object. Callers cannot tell the difference. They think they are holding your bean directly.&lt;/p&gt;

&lt;p&gt;That one trick is the real answer to a whole family of "how does Spring even do that?" questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@Transactional&lt;/code&gt; works because the proxy opens a database transaction before your method runs, and commits it after the method returns.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@Async&lt;/code&gt; works because the proxy hands your call off to run on another thread.&lt;/li&gt;
&lt;li&gt;Security and caching annotations work the same way — extra code wrapped neatly around your untouched method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also the seam the third cost was missing earlier. Back when &lt;code&gt;OrderService&lt;/code&gt; built its own gateway with &lt;code&gt;new&lt;/code&gt;, there was nowhere to slip in "wrap every payment in a transaction." Now there is: the gateway arrives from the factory, so the factory gets one chance, at build time, to hand back a wrapped version instead of the bare one. You wrote a plain method; the container wrapped it at startup. Hold on to this frame, because it keeps paying off: &lt;strong&gt;most Spring features are just the container doing extra work while it assembles your beans.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The one rule that ties it together
&lt;/h2&gt;

&lt;p&gt;All of this only works on objects the container built. The moment you build one yourself, none of it happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// built by you, not Spring&lt;/span&gt;
&lt;span class="c1"&gt;// no gateway injected — Spring never saw this object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The usual symptom is a &lt;code&gt;NullPointerException&lt;/code&gt; on a field you were sure Spring would fill in. Spring did not create the object, so it never wired it, and the field stayed &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The same bypass quietly kills proxies. Call a &lt;code&gt;@Transactional&lt;/code&gt; method on a hand-built instance, and there is no proxy around it, so no transaction ever starts. Nothing errors. The transaction simply isn't there. This is exactly why the bean-versus-&lt;code&gt;new&lt;/code&gt; distinction from earlier mattered: Spring's powers ride on objects the factory made, and skip everything it didn't.&lt;/p&gt;

&lt;p&gt;So the rule is short: &lt;strong&gt;if you want any of Spring's powers on an object, let Spring create the object.&lt;/strong&gt; Don't &lt;code&gt;new&lt;/code&gt; your beans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;Spring exists to take one job off your code: creating and connecting objects. Hand that job over, and three ideas fall out of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inversion of Control&lt;/strong&gt; is the handover itself — your code stops creating its own collaborators. &lt;strong&gt;Dependency injection&lt;/strong&gt; is how those collaborators arrive, best through the constructor. And the &lt;strong&gt;container&lt;/strong&gt; is the factory that does the work: it reads your recipes at startup, builds the objects in dependency order, caches them, and can quietly wrap each one in a proxy on the way out.&lt;/p&gt;

&lt;p&gt;That last move, the proxy, is why so much of Spring feels like magic later. It isn't magic. It is the factory doing extra work as it builds your beans. Bean scopes, AOP, transactions — everything heavier you meet from here is a variation on this one startup pass.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>backend</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
