Your First Spring Application: XML and Annotation Wiring

bee2026-10-0834 min read0 views
Without Spring Boot: assemble a container with Maven and spring-context — XML bean declarations, annotation scanning, constructor and setter injection, scopes, and a clear comparison of both styles.
1 / 91
Section
0. The 30-second version
2 / 91

No Spring Boot in this article — just Maven plus spring-context — so that you stand the Spring container up by hand exactly once: write one XML file saying "which objects exist and who needs whom", then ask the container for objects with getBean. There is only one comparison to master (XML versus annotations) and only two injection routes to tell apart (constructor injection via <constructor-arg>, property injection via <property>). Once this runs, every later claim of "Boot does it automatically" becomes a sequence of steps you can name out loud.

3 / 91
Analogy

the Spring container is a vending machine. Building an object yourself means climbing inside the machine and manufacturing a bottle; using the container means the bottles are already stocked and you simply press the slot number (getBean("helloService")) and one drops out. The slot number is the bean's id — a wrong number, a mislabelled slot or an empty row is exactly the three classic failures in the error table of Section 17. And note the singleton case: a stocked item is not remade per press. The machine holds one bottle, so you and the next person pressing the same number get the very same one.

4 / 91
Analogy

a BeanDefinition is the recipe, the bean is the dish on the table. At startup the container first copies every <bean> from your XML into a recipe (class name, constructor arguments, scope, whether it is served late), and files all of them in the registry (BeanDefinitionRegistry); only at refresh() does it cook, putting finished singletons into the warmer (singletonObjects). So the object you get from getBean is a finished dish — it is never cooked to order — which also explains why one wrong class ruins the whole table.

5 / 91
Diagram
Figure · What lives inside beans.xml
Figure · What lives inside beans.xml
6 / 91

After this article you should be able to answer three questions:

7 / 91
  1. From the moment you write new ClassPathXmlApplicationContext("applicationContext.xml"), which jobs has the container already done for me?
  2. Both <constructor-arg> and <property> "push a dependency in" — how do their creation timing and failure modes differ?
  3. Which style suits which scenario, and can one container mix both?
8 / 91
Section
1. Why start with "plain" Spring: the case for spring-context
9 / 91

Ask anyone how Spring wires a bean and the first answer is usually @SpringBootApplication. But that annotation hides too much — component scanning, auto-configuration and the embedded container are all folded into it, so you never see how the container is assembled layer by layer. In this article we deliberately avoid Spring Boot and stand up an ApplicationContext from scratch with Maven plus spring-context. Once you understand it, every piece of Boot "magic" becomes an explainable process.

10 / 91

Start with the dependency. The first question most people ask is: why not spring-core?

11 / 91
Code
Codexml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0                             https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.example</groupId>    <artifactId>spring-xml-demo</artifactId>    <version>1.0.0</version>    <packaging>jar</packaging>    <properties>        <maven.compiler.release>17</maven.compiler.release>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <spring.version>6.1.6</spring.version>    </properties>    <dependencies>        <!-- Declare just this one: the container itself -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>${spring.version}</version>        </dependency>    </dependencies></project>
Notes
  • spring-context transitively pulls in spring-core, spring-beans, spring-aop and spring-expression; you never declare them by hand
  • spring-core only holds utilities (ClassUtils, Resource, OrderComparator) — it has no container; ApplicationContext lives in spring-context
  • Choosing spring-context gives you "container + bean factory + AOP + SpEL" in one shot, which is exactly what a Boot starter ends up assembling for you

Tip: to confirm the dependency tree, run mvn dependency:tree in the project root. You will see four sibling modules hanging off spring-context — that is "declare one, get a chain".

12 / 91
Section
2. Your first bean and the main method
13 / 91

Fix the layout first so every file has a home:

14 / 91
text
spring-xml-demo/├── pom.xml└── src/main/    ├── java/com/example/    │   ├── HelloService.java    │   ├── HelloServiceImpl.java    │   ├── GreetingDao.java    │   ├── SimpleDataSource.java    │   └── Main.java    └── resources/        └── applicationContext.xml
15 / 91
Animation
Animation · How one bean comes to life
Animation · How one bean comes to life
16 / 91

Interface first, then the implementation:

17 / 91
java
package com.example;public interface HelloService {    String sayHello(String name);}
18 / 91

The implementation deliberately keeps a constructor parameter — it is our probe for verifying that injection actually happened:

19 / 91
java
package com.example;public class HelloServiceImpl implements HelloService {    private final String prefix;    // No no-arg constructor: someone (the container) must pass prefix in    public HelloServiceImpl(String prefix) {        this.prefix = prefix;    }    @Override    public String sayHello(String name) {        return prefix + ", " + name + "!";    }}
20 / 91

The entry class does only two things — start the container, fetch the bean:

21 / 91
java
package com.example;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {    public static void main(String[] args) {        // 1. Start the container: it reads applicationContext.xml from the classpath root        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        // 2. Fetch the bean by name -- note: NOT new HelloServiceImpl("Hello")        HelloService service = ctx.getBean("helloService", HelloService.class);        System.out.println(service.sayHello("Spring"));        // 3. Close the container so all singleton destroy callbacks run        ((ClassPathXmlApplicationContext) ctx).close();    }}
22 / 91

Run Main and the console prints:

23 / 91
Code
Codetext
Hello, Spring!
Notes
  • The Hello in the output is not hard-coded; it is the prefix injected from applicationContext.xml
  • The second argument of getBean("helloService", HelloService.class) performs a type check, failing fast instead of requiring a cast
  • close() is not decoration: without it, @PreDestroy and DisposableBean callbacks never fire
24 / 91

That one getBean call deserves its own look, because the same line has three possible endings: the name was never registered so it throws, a singleton comes straight out of the pool, or a prototype gets rebuilt from its blueprint every time. The animation walks all five steps, and the == check at the end is the quickest way to tell the first two apart:

25 / 91
Animation
Animation · Three outcomes of one getBean
Animation · Three outcomes of one getBean
26 / 91
Section
3. XML wiring: applicationContext.xml explained
27 / 91
Diagram
Figure 1 · What the container does with XML
Figure 1 · What the container does with XML
28 / 91

Drop the following into src/main/resources/applicationContext.xml:

29 / 91
Code
Codexml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans.xsd">    <!-- (1) Simplest bean: id is its name in the container, class is the FQCN to instantiate -->    <bean id="helloService" class="com.example.HelloServiceImpl">        <!-- (2) Constructor injection: index starts at 0, matching parameter position -->        <constructor-arg index="0" value="Hello"/>    </bean>    <!-- (3) Property injection: no-arg construct first, then setter assignment -->    <bean id="greetingDao" class="com.example.GreetingDao">        <property name="dataSource" ref="dataSource"/>        <property name="timeout" value="3000"/>    </bean>    <!-- (4) The referenced bean (ref points at this id) -->    <bean id="dataSource" class="com.example.SimpleDataSource" scope="singleton"/>    <!-- (5) Prototype scope: every getBean returns a brand-new object -->    <bean id="requestLogger" class="com.example.RequestLogger" scope="prototype"/></beans>
Notes
  • id="helloService": the bean's unique name in the container; getBean("helloService") locates it by this
  • <constructor-arg index="0" value="Hello"/>: constructor injection; index is 0-based and most reliable when names repeat
  • <property name="dataSource" ref="dataSource"/>: setter injection; ref means "reference another bean", which must exist
  • <property name="timeout" value="3000"/>: value injects a literal; Spring converts the string "3000" into an int
  • scope="singleton": the default — one instance per container; prototype creates a new one on every request

Trap: <property name="xxx"> matches a setter by method name via reflection — name="dataSource" requires a setDataSource(...). Omit it, misspell it, or expose only a field with no setter, and startup throws NotWritablePropertyException.

30 / 91

Those five lines describe the static shape. Reading one <bean> tag off the disk and filing it properly actually takes four steps — click through them, and pay attention to cell ③: until every blueprint is filed, not one object exists:

31 / 91
Diagram
FlowHow one <bean> tag lands in the container (click through it)1 / 4
Go from ① to ④; cell ③ is the one beginners always skip
→
→
→
① Locate the resource
ClassPathXmlApplicationContext("applicationContext.xml") first looks for the file on the classpath. Not finding it means FileNotFoundException — and note this happens the moment the context is constructed, before any bean is even in play. File name, letter case and whether it was ever packaged into resources are all settled here.
All clearOne line to remember: read the file → copy the blueprints → file them → produce. The first three steps hold no objects; your code runs for the first time at step ④.
32 / 91
Section
4. Annotation wiring: @Configuration and component scanning
33 / 91

Beyond XML, Spring lets a Java class describe wiring. A @Configuration class is itself a bean, and a @Bean method's name is the bean name:

34 / 91
java
package com.example;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration                    // declares a configuration class@ComponentScan("com.example")     // scans this package and its subpackages for @Componentpublic class AppConfig {    @Bean                         // the return value is registered; bean name = method name    public HelloService helloService() {        return new HelloServiceImpl("Hello");    }}
35 / 91

Business classes carry @Service and declare what they need with @Autowired — note the use of constructor injection:

36 / 91
java
package com.example;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Service                          // a semantic variant of @Component: the service layerpublic class OrderService {    private final HelloService helloService;    @Autowired                    // optional for a single constructor since 4.3, but clearer    public OrderService(HelloService helloService) {        this.helloService = helloService;    }    public String greet(String user) {        return helloService.sayHello(user);    }}
37 / 91

Startup switches to reading the config class:

38 / 91
Code
Codejava
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);OrderService orderService = ctx.getBean(OrderService.class);System.out.println(orderService.greet("Annotation"));
Notes
  • @ComponentScan only covers the configuration class's own package and below; a wrong package name is the number-one cause of "bean not found"
  • @Service / @Repository / @Controller are semantic aliases of @Component and scan identically
  • Constructor injection lets helloService be final — once constructed, the dependencies are immutable and inherently thread-safe
39 / 91
Section
5. The two styles compared
40 / 91
Table
AspectXML wiringAnnotation wiring
ReadabilityCentralized; see everything at onceLives beside the code; read locally
RefactoringBreaks when a class/package is renamedIDE rename and navigation work
Compile-time checkNone; errors surface at startupMissing class fails compilation
Cost of changeEdit config, no recompileEdit code, rebuild
Best forInfrastructure, third-party classes, ops-editable configYour own business code, fast iteration
41 / 91
Note

the two are not mutually exclusive — XML and annotation beans can coexist in one container and share the same BeanDefinitionRegistry.

42 / 91
Diagram
Figure · Two styles, one blueprint
Figure · Two styles, one blueprint
43 / 91

That table compares temperament. What actually trips people up is something far more concrete: for one given configuration, what is the word for it in each style. So play a round of pairing — the left column is what you will find in the legacy project you inherited, the right column is what you will write from article 6 onwards:

44 / 91
Match
MatchXML tags ↔ their annotation equivalentsMatched 0/8 · Missed 0
Eight pairs, each one the same fact written twice. The left column comes from the legacy project, the right from what you are about to write
Pick a card on the left first
45 / 91
Section
6. The ApplicationContext family and how BeanFactory differs
46 / 91

ApplicationContext is the high-level, user-facing interface. Its common implementations are categorized by where definitions come from:

47 / 91
Table
ImplementationDefinition sourceTypical use
ClassPathXmlApplicationContextXML on the classpathClassic XML projects
FileSystemXmlApplicationContextXML at a filesystem pathExternal, editable config
AnnotationConfigApplicationContextJava config classesAnnotation / plain-Java projects
AnnotationConfigWebApplicationContextJava config classesWeb environments
XmlWebApplicationContextReferenced from web.xmlLegacy Servlet apps
48 / 91

BeanFactory is the lowest-level container interface, with DefaultListableBeanFactory as the default implementation. The biggest difference is when instantiation happens:

49 / 91
Code
Codejava
// BeanFactory: create on demand (lazy)DefaultListableBeanFactory factory = new DefaultListableBeanFactory();// ^ only definitions are registered; no bean has been instantiated yet// ApplicationContext: pre-instantiate all singletons at startupApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");// ^ when construction returns, every non-lazy singleton already exists
Notes

Key point: remember one sentence — BeanFactory is lazy; ApplicationContext pre-instantiates singletons at startup. On top of BeanFactory, ApplicationContext layers event publishing, i18n, resource loading and AOP auto-proxying, which is why real projects almost always use ApplicationContext.

50 / 91
Section
7. Reading the startup log line by line
51 / 91

With debug logging enabled, a typical startup looks like this:

52 / 91
Code
Codetext
10:21:33.114 [main] INFO  o.s.c.s.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1b6d358610:21:33.182 [main] INFO  o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]10:21:33.251 [main] INFO  o.s.b.f.s.DefaultListableBeanFactory - Pre-instantiating singletons in ...: defining beans [helloService,greetingDao,dataSource,requestLogger]; root of factory hierarchyHello, Spring!
Notes
  • Refreshing ...: refresh() is invoked, the single entry point that orchestrates every later phase
  • Loading XML bean definitions: XmlBeanDefinitionReader turns each <bean> into a BeanDefinition
  • defining beans [helloService, greetingDao, ...]: registration is done; the bracketed order mirrors "register, then instantiate"
  • Pre-instantiating singletons: singleton pre-instantiation begins, so constructor logs appear after this line
  • Hello, Spring!: main fetched the bean and called it — the whole wiring chain works
53 / 91
Section
8. Three high-frequency traps
54 / 91
Trap

the component scan misses the package. @ComponentScan("com.example.service") scans only one subpackage, leaving an @Service under com.example.web orphaned; getBean then fails with NoSuchBeanDefinitionException: No qualifying bean of type .... First confirm where the class lives, then widen the scan path to the common parent.

55 / 91
Trap

a hand-constructed object is not managed by the container. new OrderService(new HelloServiceImpl("hi")) runs, but it is not in the container — @Autowired never fires, the AOP proxy never applies, and @Transactional is a no-op. Any class that needs container capabilities (injection, transactions, aspects) must be taken from the container, never built by hand.

56 / 91
Warning

your first circular-dependency error. A's constructor needs B and B's constructor needs A, so startup throws BeanCurrentlyInCreationException. Under XML, setter injection could break the cycle by exposing a half-built object early, so cycles often "looked fine"; switch to constructor injection and the cycle is exposed immediately. Before reaching for @Lazy, ask whether these two classes have tangled their responsibilities.

57 / 91
Section
9. Try it: a real assembly scene inside the container
58 / 91

The demo below turns "how the container creates beans and when it skips them" into toggleable switches. Flip a condition and watch the wiring results change in a chain:

59 / 91
Kernel lab
60 / 91

Once the buttons are done, ask the container yourself. This console is wired to the real in-browser kernel and every echoed line is computed on the spot — the chain it holds (dataSource → jdbcTemplate → userRepository → userService → dispatcherServlet) is a living specimen of the two injection routes from Section 3. The order below is the correct order for answering "did my bean actually get into the container":

61 / 91
Console
62 / 91
Tip

cond changes a wiring condition, and the kernel swaps in a brand-new container and runs the creation flow again, so you do not have to type boot afterwards. The status column sliding back from "created" to "not created" in beans is the other face of the same fact — new container, empty pool. It is also why logs has to be re-read every time.

63 / 91
Section
10. XML or annotations for a new project?
64 / 91
Decision
Decisionyou inherit a 2013 SSM project, the team keeps adding features, and a rewrite is off the table. How should the new module's beans be wired?
65 / 91

One step further: when you carry this wiring into a Boot project, the pom stops being "hand-pick three spring-* lines" and becomes "tick some starters". Do not copy it out — tick it once and read why the generator pairs each entry with what:

66 / 91
Generator
GeneratorWhat the pom becomes when plain spring-context moves to Bootpom.xml2 / 6
The spring-context / spring-beans / spring-core lines you hand-wrote in Section 1 arrive here as transitive dependencies of the starters, which is why none of them appear in the checkbox list. Tick Web and Test to set a baseline, then add JPA and MySQL and watch which extra scope line shows up
Output
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version> <!-- 版本由 BOM 统管,子依赖不写 version -->
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
Why each choice matters
parentInheriting 3.3.4 starter-parent means no spring-boot-starter-* needs a version; the moment someone adds an explicit version to one starter, that one wins — the most common source of dependency drift.
WebAnything that serves HTTP needs it: DispatcherServlet, embedded Tomcat and JSON mapping come inside this starter.
Testscope=test: @SpringBootTest, MockMvc and AssertJ live here; without it @Test is unresolved.
67 / 91
Section
11. Lab one: the whole XML container startup
68 / 91

Section 7 read the log; this section puts the camera inside the container. This lab has four positions — click them in order. Start with "Read & parse" to watch a file on disk become something in memory; then "Register definitions" to see recipes clipped into the registry; then "getBean in action" for the instant you press the slot number; and finally "A typo in class", the most valuable of the four, because it explains why a single wrong letter stops the whole machine. After these four, the error table in Section 17 needs no memorising.

69 / 91
Kernel lab
TeaVMInside the XML container, start to finishidle
Click parse → register → getbean → typo and watch what memory holds at the end of each stage
Scenario
Click “Run demo” to execute the AOT-compiled Java kernel right in your browser, step by step.
70 / 91
Section
12. Lab two: where a BeanDefinition comes from
71 / 91

BeanDefinition shows up three times in this article, so it deserves its own look. It is the container's instruction sheet for a bean — everything you write in XML or annotations is first translated into it, and only then does instantiation begin. The four positions show: scanning and parsing, where scope / lazy end up, what the registry itself looks like, and the most useful of all — "Several candidates", which is the root of NoUniqueBeanDefinitionException when you call getBean(XxxService.class).

72 / 91
Kernel lab
TeaVMWhere a BeanDefinition comes fromidle
Switch to registry to see the beanName → BeanDefinition table, then to multi to see why type-based lookup becomes ambiguous
Scenario
Click “Run demo” to execute the AOT-compiled Java kernel right in your browser, step by step.
73 / 91
Section
13. Lab three: the twelve steps of refresh()
74 / 91
Animation
Animation · Who gets born first during refresh()
Animation · Who gets born first during refresh()
75 / 91

new ClassPathXmlApplicationContext(...) hides a refresh() — the single method that orchestrates container startup in twelve ordered actions. A beginner does not need to memorize all twelve; two facts carry almost everything: all definitions are registered before any object is built, and any failing step aborts the whole startup. Start with "The four that matter", then look at "When one step fails", and only expand to all twelve out of curiosity.

76 / 91
Kernel lab
TeaVMThe twelve steps of refresh()idle
Start with key, then fail, and see at which step the exception is raised and how the container discards what it already built
Scenario
Click “Run demo” to execute the AOT-compiled Java kernel right in your browser, step by step.
77 / 91
Section
14. Lab four: the assembly timing of three injection styles
78 / 91

The difference between <constructor-arg> and <property> is not a style preference but two different creation routes: the first demands a matching constructor and fails outright when arguments are missing; the other calls the no-arg constructor for a half-built object and then assigns property by property, so the object always gets to exist. The fourth position, "With a cycle", explains the warning in Section 8 — why cycles booted fine in the setter era and explode immediately under constructor injection.

79 / 91
Kernel lab
TeaVMThe assembly timing of three injection stylesidle
Compare the constructor / setter / field timelines, then switch to cycle to see exactly which step breaks
Scenario
Click “Run demo” to execute the AOT-compiled Java kernel right in your browser, step by step.
80 / 91
Section
15. Sandbox: which single line of XML changes what
81 / 91

Before touching the code, change the config here. Two knobs: scope (singleton or prototype) and whether <constructor-arg> is present. The output tells you at once whether two getBean calls return the same object and whether the hashCode shapes line up — the quickest way to check "did my scope take effect".

82 / 91
Sandbox
SandboxWhich single line of XML changes what
Result
getBean twice == true
com.example.HelloServiceImpl@1b6d3586
com.example.HelloServiceImpl@1b6d3586
# the constructor log prints only once
The default shape: the whole container shares one bottle, and the slot always holds exactly that one.
83 / 91
Section
16. Quick quizzes
84 / 91
Quiz
Check yourselfAfter `ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");` finishes executing (no getBean called yet), have the container's non-lazy singleton beans already been created?
Pick one — you get feedback right away
85 / 91
Quiz
Check yourselfWhat is the fundamental difference between `<constructor-arg>` and `<property>` in XML?
Pick one — you get feedback right away
86 / 91
Section
17. Common errors cheat sheet
87 / 91
Table
Error text (fragment)Real cause30-second fixDeep dive
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [beans.xml]; nested exception is java.io.FileNotFoundException: class path resource [beans.xml] cannot be opened because it does not existWrong file name or path, or the XML sits in src/main/java and never gets packaged onto the classpathCheck the file really exists under src/main/resources; the constructor argument must match its path relative to the resources root exactlyArticle 2 · Maven and directory layout
java.lang.ClassNotFoundException: com.exmple.HelloServiceImpl (usually wrapped in a BeanCreationException)The fully qualified class name in <bean class="..."> is misspelled, or that class's dependency is absent from the classpathHit Ctrl+N in your IDE and search the class name; if it shows up, copy the package name back. The package statement is the real package nameArticle 1 · Packages and the classpath
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService' defined in class path resource [beans.xml]: Instantiation of bean failed; nested exception is ... No default constructor foundThe container needs a no-arg constructor but the class only has a parameterized one (writing any parameterized constructor removes the implicit no-arg one)Either add public UserService() {}, or write out <constructor-arg> in the XMLThe refresh and di labs in Sections 12 and 14
org.springframework.beans.NotWritablePropertyException: Invalid property 'timeout' of bean class [com.example.GreetingDao]: Bean property 'timeout' is not writable or has an invalid setter method<property name="timeout"> found no matching setTimeout(int): typo, wrong case, a field with no setter, or a mismatched parameter typeLook only at setter names: name="x" requires setX. Add the setter or rename; a private setter does not countArticle 6 · Properties and type conversion
NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.HelloService' availableThe class was never registered: the XML forgot the <bean>, an <import> did not pull that file in, or @ComponentScan does not cover the packagePrint ctx.getBeanDefinitionNames() first and look for it in the roster before deciding whether to add config or widen the scanArticle 8 · Component scanning and auto-configuration
NoSuchBeanDefinitionException: No bean named 'helloServcie' available (when looking up by id)The id in getBean("...") is misspelled or differs in case — ids are case-sensitive stringsKeep the id in a constant instead of typing it: String ID = "helloService";; for an alias use <alias name="helloService" alias="hello"/>The getbean position in Section 11
88 / 91
Tip

all six of these happen at the moment the container starts, so the debugging order is always "filename first → can the IDE jump to the class → are id and name exact → only then suspect Spring".

89 / 91

The first row of that table is what beginners hit before anything else: the container has not even started, and it already tells you a file cannot be found. Do not memorise the answer — pick out the culprit frame in that wall of text; picking wrong still explains itself:

90 / 91
Triage
Error triageBeanDefinitionStoreException

You write the XML exactly as the tutorial says, drop the file somewhere in the project, then type new ClassPathXmlApplicationContext("beans.xml") — the program exits with code 1 without ever printing a single line of your own logging.

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [beans.xml]; nested exception is java.io.FileNotFoundException: class path resource [beans.xml] cannot be opened because it does not exist
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:570)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144)
Caused by: java.io.FileNotFoundException: class path resource [beans.xml] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:208)
at com.example.Main.main(Main.java:11)
Click the frame you blame — guessing is allowed
No pressure: guess the exception first, then which line actually made the call.
91 / 91
Summary

take away three things — spring-context is the container's minimal dependency; XML wires via constructor-arg / property while annotations wire via @Configuration / @ComponentScan / @Autowired; BeanFactory is lazy while ApplicationContext pre-instantiates singletons at startup. Once the container is visible, auto-configuration is no longer mysterious.