Custom Package Scanning
About
In Spring Boot, annotations like @ComponentScan
, @EnableJpaRepositories
, and @EntityScan
are used to automatically detect and register beans, repositories, and entities during application startup.
By default, these annotations scan the packages from the location of the @SpringBootApplication
class and below. In modular or layered applications, especially when using external modules or JARs, it is often necessary to explicitly specify additional packages to scan, especially when we cannot modify the base project.
Why Custom Package Scanning Is Needed
We may need custom scanning when:
We add a new module with additional repositories or entities.
The main application class (in a base JAR) does not scan our current module.
We want to keep modules loosely coupled and modular.
We have split our domain, persistence, and business logic into separate packages or modules.
If we don’t configure it correctly:
Spring will not detect our new
@Entity
classes.@Repository
interfaces in our module will not be instantiated.Beans from our new packages will not be registered.
Common Scenarios
We are working on an extension or feature module that includes:
New
@Entity
classes (e.g.,com.my.module.entity
)New
@Repository
interfaces (e.g.,com.my.module.repository
)New
@Service
or@Component
classes (e.g.,com.my.module.service
)
The main application class resides in a base library or core project that we cannot modify.
Solution: Define a Local Configuration Class
Instead of modifying the base application class, define a new configuration class in our module to declare custom scanning behavior.
Example
@Configuration
@ComponentScan(basePackages = "com.my.module")
@EntityScan(basePackages = "com.my.module.entity")
@EnableJpaRepositories(basePackages = "com.my.module.repository")
public class MyModuleScanConfig {
// We can leave this empty. Spring will do the scanning.
}
Where to Place This Configuration
Place this config class in our own module.
It will be picked up automatically if:
It is in a package scanned by the base application.
Or we import it manually using
@Import(MyModuleScanConfig.class)
from any scanned configuration.
If not automatically scanned, we can register it manually:
@SpringBootApplication
@Import(MyModuleScanConfig.class)
public class ExtensionApplication {
public static void main(String[] args) {
SpringApplication.run(ExtensionApplication.class, args);
}
}
Or, if even this is not possible (e.g., we're adding to an existing WAR), we can create a new @Configuration
class that is picked up as part of Spring’s component scanning from a META-INF/spring.factories
file in more advanced setups.
1. ComponentScan
About
@ComponentScan
is a Spring annotation used to automatically discover and register beans in the Spring application context.
It tells Spring which packages to scan for classes annotated with:
@Component
@Service
@Repository
@Controller
@RestController
@Configuration
These annotated classes are automatically detected and registered as Spring beans without needing to declare them manually.
Default Behavior
When we use @SpringBootApplication
, it implicitly includes @ComponentScan
.
By default, it scans all packages starting from the package of the class annotated with @SpringBootApplication
and downward (i.e., all subpackages).
@SpringBootApplication // includes @ComponentScan
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
So if our @SpringBootApplication
class is in the package com.example
, all components under com.example.*
will be scanned automatically.
Syntax and Usage
1. Scanning Specific Packages
@ComponentScan(basePackages = "com.my.module")
We can also provide multiple packages:
@ComponentScan(basePackages = {
"com.my.module.service",
"com.my.module.controller"
})
2. Scanning by Class Reference
We can also reference a class instead of using a string:
@ComponentScan(basePackageClasses = MyService.class)
This is type-safe and avoids hardcoding package names.
Example with Filters
@ComponentScan(
basePackages = "com.my.module",
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyMarker.class),
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Internal.*")
)
This includes only components marked with
@MyMarker
.It excludes components whose class names match
.*Internal.*
.
Attributes
basePackages
One or more package names to scan.
basePackageClasses
One or more classes; Spring scans the packages of those classes.
includeFilters
Filters for including specific component types (with @Filter
).
excludeFilters
Filters for excluding specific types or patterns.
lazyInit
If true
, beans are created lazily instead of at startup.
nameGenerator
Custom bean name generator.
useDefaultFilters
If false
, disables default @Component
, etc. scanning.
scopedProxy
Scope proxy options (used for advanced scoping like session/request).
Common Issues and Fixes
My service/controller is not getting injected
Not in a scanned package
Add the package to @ComponentScan
Unwanted beans getting created
Default scanning includes everything
Use excludeFilters
or disable useDefaultFilters
Slow startup or memory issues in large apps
Scanning too many unnecessary packages
Limit basePackages
to only what's needed
Duplicated beans with same name
Scanning same package in multiple modules
Check overlapping scan configurations
2. EntityScan
About
@EntityScan
is a Spring Boot-specific annotation used to explicitly specify the packages to scan for JPA entities (@Entity
, @Embeddable
, @MappedSuperclass
).
Spring Boot, by default, only scans entity classes in the package (and subpackages) where the @SpringBootApplication
class resides. If our entity classes are located outside of that package, we need @EntityScan
.
@ComponentScan
does not include or cover @EntityScan
.
They serve completely different purposes, and in the context of Spring Boot and multi-module projects, we must declare both separately if our external module contains both components and JPA entities.
Why @EntityScan
is Needed ?
@EntityScan
is Needed ?By default:
@SpringBootApplication // includes @ComponentScan, @EnableAutoConfiguration
public class MainApp {}
Only scans entities under com.example
if this class is in com.example
.
If our entities are in:
package com.external.module.entity;
They will not be discovered automatically. We will encounter runtime errors such as:
Not a managed type
Unable to locate entity
To fix this, use:
@EntityScan(basePackages = "com.external.module.entity")
Where to Place @EntityScan
@EntityScan
On our main application class:
@SpringBootApplication @EntityScan(basePackages = "com.my.module.entity") public class MyApplication {}
Or in a separate
@Configuration
class:@Configuration @EntityScan(basePackages = "com.my.module.entity") public class EntityScanConfig {}
And register using:
@SpringBootApplication @Import(EntityScanConfig.class) public class MyApp {}
Syntax
Single Package
@EntityScan(basePackages = "com.example.entity")
Multiple Packages
@EntityScan(basePackages = {
"com.example.entity",
"com.shared.common.entity"
})
Type-Safe with Class Reference
@EntityScan(basePackageClasses = MyEntity.class)
This is safer during refactoring as it avoids hardcoded package strings.
Attributes
basePackages
Array of package names to scan for entities.
basePackageClasses
Type-safe way to scan the package of the given class.
3. EnableJpaRepositories
About
@EnableJpaRepositories
is a Spring Data annotation used to enable scanning and registration of Spring Data JPA repository interfaces, such as those extending:
JpaRepository
CrudRepository
PagingAndSortingRepository
It is responsible for detecting our repository interfaces, generating proxy implementations, and integrating them with the JPA entity manager.
Does @EnableJpaRepositories
include @EntityScan
?
No, it does not.
@EnableJpaRepositories
only scans for repository interfaces likeUserRepository extends JpaRepository<User, Long>
.It does not scan or register JPA entity classes (
@Entity
annotated classes).If our entities are outside the default scan path, we must use
@EntityScan
explicitly.
Does @EntityScan
include @EnableJpaRepositories
?
No, it does not.
@EntityScan
only registers entity classes (@Entity
,@Embeddable
,@MappedSuperclass
) so that JPA can map them to database tables.It does not scan or register repository interfaces.
We still need
@EnableJpaRepositories
if the repository interfaces are outside the main package.
Does @ComponentScan
include @EnableJpaRepositories
?
No, it does not.
@ComponentScan
detects and registers Spring beans annotated with@Component
,@Service
,@Controller
,@RestController
, etc.It does not process repository interfaces or generate their implementations.
Repository interfaces are not annotated with
@Component
, so@ComponentScan
will not register them.
Why is it Needed ?
Spring Boot, by default, scans repositories in the same package or subpackages of our main application class (@SpringBootApplication
). If our repository interfaces are located outside of this default scope, we must explicitly specify the package using @EnableJpaRepositories
.
Default Behavior
If we don’t specify @EnableJpaRepositories
, Spring Boot still scans for repositories, but only under the default package (where our main class resides).
If we need to include repositories from another module, library, or unrelated package, we must declare:
@EnableJpaRepositories(basePackages = "com.external.module.repository")
Example
@EnableJpaRepositories(basePackages = "com.my.module.repository")
Type-Safe Alternative
@EnableJpaRepositories(basePackageClasses = MyRepository.class)
With Additional Configuration
@EnableJpaRepositories(
basePackages = "com.my.module.repository",
entityManagerFactoryRef = "myEntityManagerFactory",
transactionManagerRef = "myTransactionManager"
)
Attributes
basePackages
Array of package names to scan for repository interfaces.
basePackageClasses
Type-safe alternative to basePackages
, scans package of the given class.
includeFilters
Used to include specific types.
excludeFilters
Used to exclude certain classes from being registered as repositories.
repositoryFactoryBeanClass
Custom factory bean to create repositories.
entityManagerFactoryRef
Bean name of the EntityManagerFactory
to associate with these repositories.
transactionManagerRef
Bean name of the PlatformTransactionManager
for this repository group.
considerNestedRepositories
Whether nested interfaces should be considered. Default is false
.
Does @ComponentScan
register JPA repository interfaces
@ComponentScan
register JPA repository interfacesNo
For example:
public interface UserRepository extends JpaRepository<User, Long> {
// no implementation provided
}
Even though Spring dynamically creates a proxy class and marks it as a @Repository
, this behavior is triggered by:
@EnableJpaRepositories
Because @ComponentScan
works with actual class files annotated with @Component
, @Repository
, etc. It does not dynamically generate or proxy anything.
But @EnableJpaRepositories
activates Spring Data’s infrastructure, which:
Scans for repository interfaces
Dynamically generates proxy beans
Registers them in the application context
4. Import
About
@Import
is a Spring annotation used to manually import one or more @Configuration
classes (or component classes) into the Spring application context.
It gives us a way to programmatically include configurations or beans that are not automatically picked up by component scanning.
@Import
does not scan packages. It registers specific classes.It is often used to bridge between modules in a modular project.
It can also import non-
@Configuration
classes such as regular components orImportSelector
/ImportBeanDefinitionRegistrar
implementations.
Why and When to Use ?
We use @Import
when:
We have configuration classes in external modules or libraries.
We want to load Java-based configuration from other packages or jars.
We do not want to rely on
@ComponentScan
to find those classes.We want explicit, modular control over what configuration gets loaded.
We are registering beans dynamically or combining multiple configuration sources.
Example
Importing a Single Configuration Class
@Configuration
public class MyConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
Then in our main class:
@SpringBootApplication
@Import(MyConfig.class)
public class MyApp {}
This tells Spring Boot to include MyConfig
during context initialization even if it is not in a scanned package.
Importing Multiple Classes
@Import({MyConfig.class, AnotherConfig.class, SecurityConfig.class})
Best Practices
Prefer
@Import
for fine-grained and modular inclusion of configurations.Use
@Import
instead of@ComponentScan
for external libraries or JARs where scanning may not be desirable.Avoid excessive or scattered usage of
@Import
; centralize imports logically.
Last updated
Was this helpful?