Week 1 Day 5 — Component Scanning and Package Structure
Goal
Today I want to understand how Spring finds my classes and registers them as beans.
Main questions:
- What is component scanning?
- What does
@ComponentScando? - What does
@SpringBootApplicationscan by default? - Why does package structure matter?
- Why can a class with
@Servicestill not become a bean? - How can I customize component scanning?
- What are stereotype annotations?
- What are common real-world bugs with component scanning?
- What are common exam traps?
1. Quick Review
From previous days:
- A Spring bean is an object managed by Spring.
- Spring needs to know which classes should become beans.
- Beans can be registered with
@Component,@Service,@Repository,@Controller,@RestController, or@Bean. ApplicationContextstores and manages beans.BeanDefinitionis metadata for creating a bean.
Today I focus on this question:
How does Spring find my annotated classes?
The answer is:
Component scanning.
2. What Is Component Scanning?
Component scanning means:
Spring scans packages to find classes annotated with Spring stereotype annotations and registers them as beans.
Example:
@Service
public class OrderService {
}
This class can become a bean only if Spring scans the package where this class is located.
Important sentence:
Annotation alone is not enough. The class must also be inside the component scan path.
3. What Does Spring Look For?
During component scanning, Spring looks for annotations such as:
@Component
@Service
@Repository
@Controller
@RestController
@Configuration
These are called stereotype annotations.
If Spring finds one of these annotations, it can register a BeanDefinition.
Later, it creates the actual bean.
4. Component Scanning Flow
Simplified flow:
1. Spring application starts.
2. ApplicationContext is created.
3. Spring checks the component scan base package.
4. Spring scans classes inside that package and subpackages.
5. Spring finds annotations like @Service and @Repository.
6. Spring registers BeanDefinitions.
7. Spring creates beans.
8. Spring injects dependencies.
Memory sentence:
Component scanning finds classes. Bean creation creates objects.
5. @ComponentScan
The annotation responsible for scanning is:
@ComponentScan
Example:
@Configuration
@ComponentScan("com.example.app")
public class AppConfig {
}
This tells Spring:
Scan com.example.app and its subpackages.
So Spring scans:
com.example.app
com.example.app.service
com.example.app.repository
com.example.app.controller
6. Spring Boot and @SpringBootApplication
In Spring Boot, we usually do not write @ComponentScan directly.
We write:
@SpringBootApplication
public class MyApplication {
}
But @SpringBootApplication already includes:
@Configuration
@EnableAutoConfiguration
@ComponentScan
Very important exam sentence:
@SpringBootApplicationincludes@ComponentScan.
7. Default Scan Package in Spring Boot
Spring Boot starts scanning from the package where the main application class is located.
Example:
package com.example.kanzlei;
@SpringBootApplication
public class KanzleiApplication {
}
Spring scans:
com.example.kanzlei
com.example.kanzlei.controller
com.example.kanzlei.service
com.example.kanzlei.repository
com.example.kanzlei.config
It scans the main package and all subpackages.
8. Good Package Structure
Good structure:
com.example.kanzlei
├── KanzleiApplication.java
├── controller
│ └── TaskController.java
├── service
│ └── TaskService.java
├── repository
│ └── TaskRepository.java
├── entity
│ └── Task.java
├── dto
│ └── TaskResponse.java
└── config
└── SecurityConfig.java
This is good because the main class is in the root package:
com.example.kanzlei
All other classes are under it.
Spring can scan everything.
9. Bad Package Structure
Bad structure:
com.example.app
└── KanzleiApplication.java
com.example.service
└── TaskService.java
com.example.repository
└── TaskRepository.java
If the main class is in:
com.example.app
Spring scans:
com.example.app
But it does not automatically scan:
com.example.service
com.example.repository
So TaskService and TaskRepository may not become beans.
10. Real Bug Example
Imagine this class exists:
package com.example.service;
@Service
public class TaskService {
}
And the main class is:
package com.example.app;
@SpringBootApplication
public class MyApplication {
}
Spring scans:
com.example.app
But TaskService is in:
com.example.service
Result:
TaskService is not found.
TaskService is not registered as a bean.
Application may fail with "No qualifying bean of type TaskService".
11. Best Practice
Put your main application class in the root package.
Good:
com.steve.klarsync
├── KlarsyncApplication.java
├── task
├── user
├── client
├── document
└── config
Bad:
com.steve.klarsync.app
└── KlarsyncApplication.java
com.steve.klarsync.task
com.steve.klarsync.user
com.steve.klarsync.client
Why bad?
Because com.steve.klarsync.task is not under com.steve.klarsync.app.
12. Simple Rule
Use this rule:
The main Spring Boot application class should be placed in the highest/root package of the application.
Example:
package de.klarsync;
@SpringBootApplication
public class KlarsyncApplication {
}
Then put other packages under:
de.klarsync.task
de.klarsync.user
de.klarsync.client
de.klarsync.security
de.klarsync.config
13. Stereotype Annotations
These annotations help Spring understand the role of a class.
@Component
Generic Spring-managed component.
@Component
public class SlugGenerator {
}
Use when the class does not clearly belong to service, repository, or controller layer.
@Service
Business logic layer.
@Service
public class TaskService {
}
Use for application services and domain use cases.
@Repository
Persistence layer.
@Repository
public class JdbcTaskRepository {
}
Use for classes that talk to the database.
Special point:
@Repositorycan enable persistence exception translation.
@Controller
Spring MVC controller for returning views.
@Controller
public class HomeController {
}
Usually used for server-rendered HTML pages.
@RestController
REST API controller.
@RestController
@RequestMapping("/api/tasks")
public class TaskController {
}
@RestController includes:
@Controller
@ResponseBody
@Configuration
Configuration class.
@Configuration
public class AppConfig {
}
Often contains @Bean methods.
14. Important: @Configuration Is Also a Component
@Configuration is also discovered by component scanning.
Example:
@Configuration
public class TimeConfig {
@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
If TimeConfig is inside the scan path, Spring finds it.
Then Spring processes the @Bean method and registers Clock as a bean.
15. @Bean Still Needs Configuration Class Registration
Example:
@Configuration
public class TimeConfig {
@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
This works if TimeConfig is found by component scanning.
But if TimeConfig is outside the scan path, Spring does not find it.
Then the clock bean is not registered.
Exam trap:
@Beanmethods are only processed if the configuration class itself is registered.
16. How to Customize Component Scanning
You can explicitly define scan packages.
Example:
@SpringBootApplication(scanBasePackages = "com.example")
public class MyApplication {
}
This tells Spring to scan:
com.example
Another way:
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}
17. Multiple Base Packages
You can scan multiple packages:
@SpringBootApplication(scanBasePackages = {
"com.example.app",
"com.example.shared"
})
public class MyApplication {
}
Or:
@ComponentScan(basePackages = {
"com.example.app",
"com.example.shared"
})
But best practice is still:
Put your application class in the root package and avoid custom scan configuration unless necessary.
18. Type-Safe Alternative: basePackageClasses
Instead of writing package names as strings, you can use classes.
Example:
@ComponentScan(basePackageClasses = {
TaskService.class,
SharedConfig.class
})
public class AppConfig {
}
This is safer because refactoring class packages is easier than updating string package names manually.
19. Include and Exclude Filters
@ComponentScan can include or exclude classes.
Example:
@ComponentScan(
basePackages = "com.example",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Deprecated.class
)
)
This is more advanced.
For the certification, know that component scanning can be customized, but most questions focus on default scanning.
20. Real Question: Why Is My Service Not Injected?
Example error:
Parameter 0 of constructor in TaskController required a bean of type 'TaskService' that could not be found.
Possible reasons:
TaskServicehas no@Service,@Component, or@Bean.TaskServiceis outside the scanned package.TaskServicehas a profile that is not active.TaskServiceis conditional and the condition is false.TaskServicecannot be created because one of its dependencies is missing.- The wrong class or package is imported.
- The test slice does not load this bean.
Most common reasons:
Missing annotation
Outside component scan
Missing dependency
21. Real Question: Does @Service Always Create a Bean?
No.
This class:
@Service
public class TaskService {
}
becomes a bean only if Spring scans the package containing it.
So the correct answer is:
@Servicemarks the class as a candidate for component scanning. It becomes a bean only if it is discovered by the scan.
22. Real Question: Does @ComponentScan Scan the Whole Project?
No.
By default, it scans from a base package.
In Spring Boot, the base package is usually the package of the class annotated with @SpringBootApplication.
It does not automatically scan the whole source code.
23. Real Question: Does Spring Scan External Libraries?
Not automatically in the same way.
Spring scans configured base packages.
But Spring Boot auto-configuration can register beans from libraries through a different mechanism.
Important distinction:
Component scanning finds my annotated classes.
Auto-configuration registers framework/library beans based on conditions.
Example:
- My
TaskServiceis found by component scanning. - Spring Boot creates
DispatcherServletthrough auto-configuration.
24. Component Scanning vs Auto-Configuration
| Topic | Component Scanning | Auto-Configuration |
|---|---|---|
| Purpose | Find my classes | Configure Spring Boot infrastructure |
| Based on | packages and annotations | classpath, properties, conditions |
| Example | @Service TaskService | embedded Tomcat, DispatcherServlet |
| Annotation | @ComponentScan | @EnableAutoConfiguration |
| Included in | @SpringBootApplication | @SpringBootApplication |
Memory sentence:
Component scanning finds my beans. Auto-configuration creates Spring Boot infrastructure beans.
25. Component Scanning vs @Bean
| Topic | Component Scanning | @Bean |
|---|---|---|
| How bean is registered | Spring finds annotated class | Method return value becomes bean |
| Best for | My own classes | Third-party/custom objects |
| Example | @Service TaskService | @Bean Clock |
| Requires scan? | class must be scanned | config class must be registered |
26. Component Scanning and Tests
Sometimes a bean works in the real app but not in a test.
Example:
@WebMvcTest(TaskController.class)
class TaskControllerTest {
}
This test only loads the web layer.
It does not load all services.
So this may fail:
No qualifying bean of type TaskService
Fix:
@MockBean
private TaskService taskService;
Important:
Test slice annotations load only part of the application context.
This is not exactly a component scanning problem, but it looks similar.
27. Component Scanning and Profiles
A class may be scanned but not active because of a profile.
Example:
@Service
@Profile("prod")
public class RealEmailService {
}
This bean is created only when the prod profile is active.
If the active profile is dev, Spring does not create it.
28. Component Scanning and Conditional Beans
A class may be conditional.
Example:
@Component
@ConditionalOnProperty(name = "feature.audit.enabled", havingValue = "true")
public class AuditService {
}
This bean is created only if the property matches.
If not, Spring skips it.
This is common in Spring Boot.
29. Component Scanning and Bean Names
Default bean name uses the class name with lowercase first letter.
Example:
@Service
public class TaskService {
}
Bean name:
taskService
Example:
@Component
public class EmailNotificationSender {
}
Bean name:
emailNotificationSender
Custom name:
@Service("mainTaskService")
public class TaskService {
}
Bean name:
mainTaskService
30. Component Scanning and Interfaces
Spring cannot instantiate an interface directly.
Example:
public interface PaymentProvider {
}
This alone is not a bean.
Spring needs an implementation:
@Component
public class StripePaymentProvider implements PaymentProvider {
}
Then Spring can inject by interface type:
@Service
public class CheckoutService {
public CheckoutService(PaymentProvider paymentProvider) {
}
}
This works if there is exactly one implementation bean.
31. Component Scanning and Abstract Classes
Spring cannot normally instantiate abstract classes.
Example:
@Component
public abstract class BaseService {
}
This is not useful as a normal bean because Spring cannot create an abstract class instance.
But subclasses can be beans:
@Service
public class TaskService extends BaseService {
}
32. Component Scanning and Inner Classes
Spring usually scans top-level classes.
Static nested classes can sometimes be registered, especially in configuration or tests, but normal application components should be top-level classes.
Best practice:
Keep Spring components as clear top-level classes.
33. Component Scanning and Final Classes
A final class can be registered as a bean.
But final classes can be problematic when Spring needs to create a class-based proxy, for example for AOP or transactions.
Example:
@Service
public final class PaymentService {
}
The bean may be created.
But proxying can become a problem later.
We will study proxies in AOP week.
34. Component Scanning and Kotlin
In Kotlin, classes are final by default.
Spring often needs classes to be open for proxying.
That is why Kotlin Spring projects often use:
kotlin("plugin.spring")
This opens Spring-annotated classes automatically.
This is useful for your Kotlin/Spring background.
Exam focus is usually Java, but the proxy idea is important.
35. Real Debug Checklist
When a bean is not found, check this:
## Bean Not Found Debug Checklist
[ ] Does the class have `@Component`, `@Service`, `@Repository`, `@Controller`, `@RestController`, or is it created by `@Bean`?
[ ] Is the class inside the package scanned by Spring?
[ ] Is the main application class in the root package?
[ ] Is the active profile correct?
[ ] Does the bean have a condition that is false?
[ ] Are all constructor dependencies available?
[ ] Am I using a test slice like `@WebMvcTest` or `@DataJpaTest`?
[ ] Did I import the correct annotation package?
[ ] Is the class concrete, not abstract?
[ ] Is there a circular dependency?
36. Real Exam Question: Package Structure
Question:
package com.example.app;
@SpringBootApplication
public class MyApplication {
}
package com.example.service;
@Service
public class UserService {
}
Will UserService be discovered automatically?
Answer:
No. By default, Spring Boot scans from the package of the main application class, which is com.example.app. UserService is in com.example.service, which is not a subpackage of com.example.app. Therefore it will not be discovered unless scanning is customized.
37. Real Exam Question: Good Package Structure
Question:
package com.example;
@SpringBootApplication
public class MyApplication {
}
package com.example.service;
@Service
public class UserService {
}
Will UserService be discovered?
Answer:
Yes. The main application class is in com.example, so Spring scans com.example and its subpackages. com.example.service is a subpackage, so UserService can be discovered.
38. Real Exam Question: @SpringBootApplication
Question:
What three annotations are included in @SpringBootApplication?
Answer:
@SpringBootApplication includes:
@Configuration
@EnableAutoConfiguration
@ComponentScan
39. Real Exam Question: @Service
Question:
Does @Service itself guarantee that a class becomes a Spring bean?
Answer:
No. @Service marks the class as a candidate for component scanning. The class becomes a bean only if it is found by component scanning or otherwise registered.
40. Real Exam Question: @Bean
Question:
@Configuration
public class AppConfig {
@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
What becomes the bean?
Answer:
The return value of the clock() method becomes a Spring bean. By default, the bean name is clock, and the bean type is Clock.
41. Real Exam Question: Config Outside Scan
Question:
If AppConfig contains a @Bean method but AppConfig itself is outside component scanning, will the bean be created?
Answer:
No, not automatically. The configuration class must be registered with Spring. If it is outside component scanning and not imported or otherwise registered, Spring will not process its @Bean methods.
42. Real Exam Question: Component Scan Base Package
Question:
Where does Spring Boot start component scanning by default?
Answer:
Spring Boot starts component scanning from the package of the class annotated with @SpringBootApplication and scans its subpackages.
43. Real Exam Question: Custom Scan
Question:
How can I tell Spring Boot to scan another package?
Answer:
I can use:
@SpringBootApplication(scanBasePackages = "com.example")
public class MyApplication {
}
or use:
@ComponentScan(basePackages = "com.example")
44. Real Exam Question: Component Scan vs Auto-Configuration
Question:
What is the difference between component scanning and auto-configuration?
Answer:
Component scanning finds application classes annotated with stereotypes such as @Component, @Service, and @Repository. Auto-configuration creates Spring Boot infrastructure beans based on classpath, properties, existing beans, and conditions. Component scanning is for my application beans; auto-configuration is for Boot-provided setup.
45. Real Exam Question: Bean Not Found
Question:
What are common reasons for this error?
No qualifying bean of type 'EmailService' available
Answer:
Common reasons are: EmailService is not annotated or registered with @Bean, it is outside the component scan path, its active profile does not match, a condition prevents it from being created, one of its dependencies is missing, or the current test slice does not load it.
46. Interview Answer
Question:
What is component scanning in Spring?
Good answer:
Component scanning is the process where Spring scans configured packages to find classes annotated with stereotype annotations such as @Component, @Service, @Repository, and @Controller. When Spring finds these classes, it registers bean definitions for them and later creates the actual beans. In Spring Boot, component scanning is enabled by @SpringBootApplication, which includes @ComponentScan. By default, Spring Boot scans from the package of the main application class and its subpackages.
47. Interview Answer
Question:
Why should the main Spring Boot class be placed in the root package?
Good answer:
The main Spring Boot class should be placed in the root package because Spring Boot starts component scanning from the package of the class annotated with @SpringBootApplication. If the main class is too deep in the package structure, Spring may not scan services, repositories, controllers, or configuration classes in sibling packages. Placing the main class in the root package ensures that all subpackages are scanned automatically.
48. Interview Answer
Question:
Why can a class annotated with
@Servicestill not be found?
Good answer:
A class annotated with @Service may not be found if it is outside the component scan path. The annotation marks it as a candidate for component scanning, but Spring still has to scan its package. Other reasons include missing active profiles, conditional annotations, missing constructor dependencies, or test slices that do not load the full application context.
49. Interview Answer
Question:
What is the difference between component scanning and
@Beanregistration?
Good answer:
Component scanning registers beans by finding classes annotated with stereotypes such as @Component, @Service, or @Repository. This is usually used for application classes that I own. @Bean registration happens when Spring calls a method inside a configuration class and registers the return value as a bean. This is useful for third-party objects or objects that need custom creation logic.
50. Tiny Code Practice
Create this structure:
de.klarsync
├── KlarsyncApplication.java
├── task
│ ├── TaskController.java
│ └── TaskService.java
└── config
└── TimeConfig.java
Main class:
package de.klarsync;
@SpringBootApplication
public class KlarsyncApplication {
public static void main(String[] args) {
SpringApplication.run(KlarsyncApplication.class, args);
}
}
Service:
package de.klarsync.task;
@Service
public class TaskService {
}
Config:
package de.klarsync.config;
@Configuration
public class TimeConfig {
@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
Question:
Will
TaskServiceandClockbe registered as beans?
Answer:
Yes. KlarsyncApplication is in de.klarsync, so Spring scans de.klarsync and all subpackages. It finds TaskService in de.klarsync.task and TimeConfig in de.klarsync.config. Then it processes the @Bean method and creates the Clock bean.
51. Tiny Bug Practice
Bad structure:
de.klarsync.app
└── KlarsyncApplication.java
de.klarsync.task
└── TaskService.java
Main class:
package de.klarsync.app;
@SpringBootApplication
public class KlarsyncApplication {
}
Service:
package de.klarsync.task;
@Service
public class TaskService {
}
Question:
Will
TaskServicebe discovered?
Answer:
No. Spring scans from de.klarsync.app. The package de.klarsync.task is not a subpackage of de.klarsync.app. So TaskService is outside the default scan path.
Possible fixes:
- Move the main class to
de.klarsync. - Use
scanBasePackages = "de.klarsync". - Use explicit
@ComponentScan.
Best fix:
Move the main class to the root package.
Practice Questions and Answers
Question 1
What is component scanning?
Answer:
Component scanning is the process where Spring scans configured packages to find classes annotated with stereotype annotations such as @Component, @Service, @Repository, and @Controller. Spring registers these classes as bean definitions and later creates beans from them.
Question 2
What annotation enables component scanning?
Answer:
Component scanning is enabled by @ComponentScan.
Question 3
Does @SpringBootApplication include @ComponentScan?
Answer:
Yes. @SpringBootApplication includes @ComponentScan, together with @Configuration and @EnableAutoConfiguration.
Question 4
Where does Spring Boot start scanning by default?
Answer:
Spring Boot starts scanning from the package of the class annotated with @SpringBootApplication and scans its subpackages.
Question 5
Why should the main Spring Boot class be in the root package?
Answer:
The main class should be in the root package so that Spring scans all application subpackages automatically. If the main class is too deep, sibling packages may not be scanned.
Question 6
Does @Service always guarantee that a class becomes a bean?
Answer:
No. @Service marks a class as a candidate for component scanning. It becomes a bean only if Spring scans its package or it is otherwise registered.
Question 7
What are stereotype annotations?
Answer:
Stereotype annotations are annotations that mark a class as a Spring-managed component and also express its role in the application, such as service, repository, or controller.
Question 8
Name five stereotype annotations.
Answer:
Five stereotype annotations are:
@Component
@Service
@Repository
@Controller
@RestController
Also important:
@Configuration
Question 9
What is the difference between @Component and @Service?
Answer:
@Component is a generic Spring-managed component. @Service is a specialization of @Component used for service-layer classes that contain business logic.
Question 10
What is special about @Repository?
Answer:
@Repository marks a persistence-layer class and can enable persistence exception translation into Spring’s DataAccessException hierarchy.
Question 11
What does @RestController include?
Answer:
@RestController includes @Controller and @ResponseBody.
Question 12
What is the difference between component scanning and @Bean?
Answer:
Component scanning registers beans by finding annotated classes. @Bean registers the return value of a method inside a configuration class. Component scanning is usually used for my own classes, while @Bean is useful for third-party or custom-created objects.
Question 13
What must happen for a @Bean method to be processed?
Answer:
The configuration class containing the @Bean method must itself be registered with Spring, usually by component scanning, @Import, or direct configuration registration.
Question 14
What is the default bean name for this class?
@Service
public class EmailService {
}
Answer:
The default bean name is:
emailService
Question 15
Will this service be scanned?
package com.example.app;
@SpringBootApplication
public class MyApplication {
}
package com.example.app.service;
@Service
public class UserService {
}
Answer:
Yes. UserService is in com.example.app.service, which is a subpackage of com.example.app.
Question 16
Will this service be scanned?
package com.example.app;
@SpringBootApplication
public class MyApplication {
}
package com.example.service;
@Service
public class UserService {
}
Answer:
No. com.example.service is not a subpackage of com.example.app, so it is outside the default scan path.
Question 17
How can I customize the scan base package?
Answer:
I can customize the scan base package with:
@SpringBootApplication(scanBasePackages = "com.example")
or:
@ComponentScan(basePackages = "com.example")
Question 18
What is the difference between component scanning and auto-configuration?
Answer:
Component scanning finds my application classes annotated with stereotypes like @Service or @Repository. Auto-configuration creates Spring Boot infrastructure beans based on classpath, properties, existing beans, and conditions.
Question 19
Why might a bean not be found even though the class has @Service?
Answer:
Possible reasons include: the class is outside component scanning, missing active profile, false condition, missing constructor dependency, test slice does not load the bean, wrong annotation import, or the class cannot be instantiated.
Question 20
What should I check when I see No qualifying bean of type ... available?
Answer:
I should check: annotation, package scan path, main application class location, active profile, conditions, constructor dependencies, test slice configuration, correct imports, and whether the class is concrete.
Final Memory Sentences
- Component scanning finds annotated classes and registers them as beans.
@ComponentScanenables component scanning.@SpringBootApplicationincludes@ComponentScan.- Spring Boot scans from the package of the main application class by default.
- The main application class should be in the root package.
@Serviceis only a candidate unless Spring scans it.@Configurationclasses must be registered for their@Beanmethods to run.- Component scanning finds my application beans.
- Auto-configuration creates Spring Boot infrastructure beans.
@Componentis generic.@Serviceis for business logic.@Repositoryis for persistence and exception translation.@RestControllerequals@Controllerplus@ResponseBody.- A bean not found error often means missing annotation, wrong package, inactive profile, false condition, or missing dependency.