skip to content

What are 'primary sources' passed to SpringApplication, and how do they differ from component scanning?

level: middleimportance: should knowfreq 40%

answer

  1. seed classes registered before refresh
  2. usually one @SpringBootApplication class
  3. @ComponentScan grows the rest
  4. add sources for configs outside scanned package
  5. class / package / XML resource can be a source

basics

~20 s

Primary sources are the classes (or bean-definition sources) you hand to SpringApplication to seed the context — usually your one @SpringBootApplication class. Component scanning then discovers the rest of your beans from that class's package downward.

solid answer

~40 s

Primary sources are the initial bean-definition sources SpringApplication registers into the context — the classes you pass to run() or add via addPrimarySources(). Typically it's the single @SpringBootApplication class. These sources are the seed: Boot registers them as configuration, and because @SpringBootApplication includes @ComponentScan and @EnableAutoConfiguration, that seed transitively pulls in your scanned @Components and all auto-configuration. So you rarely pass more than one. You'd pass additional primary sources when you want extra @Configuration classes that aren't reachable by the default component scan (e.g., a config in a different base package), or to compose multiple configs in tests. Sources can also be XML resources or package names, but class-based configuration is the norm. They're 'primary' because SpringApplication distinguishes them from sources added later programmatically.

code

java · 11 lines
java
// Single primary source — the common case:
SpringApplication.run(DemoApplication.class, args);

// Multiple primary sources (e.g. a config outside the scanned package):
SpringApplication app = new SpringApplication(DemoApplication.class, OutOfPackageConfig.class);
app.run(args);

// Or add later:
SpringApplication app2 = new SpringApplication(DemoApplication.class);
app2.addPrimarySources(java.util.List.of(OutOfPackageConfig.class));
app2.run(args);

go deeper

for a junior

Should know it's the class(es) passed to run(), normally the main app class.

for a middle

Should distinguish explicit sources from component scanning and know how to add extra sources.

for a senior

Should explain source types (class/package/resource) and when to add configs outside the scan.

for a principal

Should use sources deliberately for context composition, test slices, and parent/child hierarchies.

## Definition When you write `SpringApplication.run(MyApp.class, args)`, `MyApp.class` is a **primary source**. Internally `SpringApplication` keeps a `Set<Class<?>> primarySources` (plus a general `Set<Object> sources` you can add). These are the objects Boot loads as **bean definitions** before refreshing the context, via a `BeanDefinitionLoader`. A source can be: - a `@Configuration`/`@Component` **class** (by far the most common), - a **package name** (String) to scan, - an XML or Groovy **resource** location. ## Why usually just one The conventional single source is your `@SpringBootApplication` class. Because that annotation bundles `@ComponentScan` (scanning its own package and sub-packages) and `@EnableAutoConfiguration`, registering just that one class triggers discovery of every other `@Component`, `@Service`, `@RestController`, `@Configuration`, etc., in your codebase, plus all matching auto-configuration. So the single primary source is the seed from which the whole bean graph grows. ## Primary sources vs component scanning - **Primary sources** are *explicitly* registered — Boot always processes them. - **Component scanning** is a *mechanism triggered by* one of those sources (`@ComponentScan`) that *discovers additional* beans by package. They're complementary: the primary source turns scanning on; scanning finds the rest. A class that lives **outside** the scanned packages is invisible to scanning — to include it you must add it as an explicit source (or `@Import` it). ## Adding more sources - Constructor: `new SpringApplication(AppConfig.class, ExtraConfig.class)`. - `app.addPrimarySources(Collections.singleton(ExtraConfig.class))`. - `SpringApplicationBuilder`: `.sources(ExtraConfig.class)` / `.sources(ParentConfig.class).child(ChildConfig.class)`. - The `getSources()`/`setSources(...)` collection for non-primary (String/resource) sources. ## When to add extra sources - A `@Configuration` in a package **not** under the main class (avoids widening `@ComponentScan` basePackages). - **Tests** composing several slice configs. - **Parent/child context** hierarchies via the builder, where each level gets its own sources. ## Gotchas - Passing a class that is **not** a configuration (no stereotype/@Configuration) usually contributes nothing useful. - Duplicating a class both as an explicit source and via component scan is harmless (Boot dedups bean definitions by name) but signals a package-layout smell. - If your beans 'aren't found', it's almost always because they sit **outside** the primary source's package and aren't added as a source or `@Import`ed.

  • Why is one primary source usually enough?
    Because @SpringBootApplication includes @ComponentScan and @EnableAutoConfiguration, so that single seed transitively registers all scanned beans and auto-configuration.
  • A @Configuration class isn't being picked up — likely cause?
    It lives outside the component-scan base package. Either move it under the main class's package, add it as a primary source, or @Import it.

saying these in an interview costs you the question

  • Confusing primary sources with the full list of every bean
  • Thinking you must list every @Configuration class as a source
  • Believing component scanning finds classes in unrelated packages automatically

context