In Spring, managing dependencies and configurations is commonly done using Java-based @Configuration
classes. These classes allow you to define the beans and their dependencies programmatically. Here’s a step-by-step guide on how to manage dependencies with @Configuration
classes:
1. Use the @Configuration
Annotation
Mark your class with the @Configuration
annotation. This tells Spring that the class defines one or more beans to be managed by the Spring container.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
// Define beans here
}
2. Define Beans with the @Bean
Annotation
Within the @Configuration
class, use the @Bean
annotation to define individual beans. Methods annotated with @Bean
will produce bean instances that will be managed by the container.
import org.springframework.context.annotation.Bean;
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
@Bean
public MyRepository myRepository() {
return new MyRepository();
}
}
In this example, MyService
and MyRepository
will be registered as beans in the Spring context.
3. Inject Dependencies Between Beans
You can inject dependencies by passing other beans as method parameters. Spring resolves these dependencies automatically.
@Configuration
public class AppConfig {
@Bean
public MyRepository myRepository() {
return new MyRepository();
}
@Bean
public MyService myService(MyRepository myRepository) {
return new MyService(myRepository);
}
}
Here, MyService
depends on MyRepository
. Spring automatically resolves myRepository
when creating the MyService
bean.
4. Use @Primary
for Bean Prioritization
If there are multiple beans of the same type, you can use the @Primary
annotation to set the default bean to be used during injection.
@Configuration
public class AppConfig {
@Bean
@Primary
public MyRepository mainRepository() {
return new MyRepository();
}
@Bean
public MyRepository backupRepository() {
return new MyRepository();
}
}
5. Use @Qualifier
to Avoid Ambiguities
For cases where multiple beans of the same type exist but you don’t want to use the primary one, use the @Qualifier
annotation along with the bean name.
@Bean("backupRepository")
public MyRepository createBackupRepository() {
return new MyRepository();
}
Inject it as follows:
@Autowired
@Qualifier("backupRepository")
private MyRepository myRepository;
6. Leveraging Externalized Properties
You can link beans to properties defined in an application.properties
file by using the @Value
annotation or @ConfigurationProperties
.
Using @Value
:
@Configuration
public class AppConfig {
@Value("${app.service.name}")
private String serviceName;
@Bean
public MyService myService() {
return new MyService(serviceName);
}
}
7. Advance to Component Scanning (@Component
)
Instead of manually defining @Bean
methods, use annotations like @Component
, @Service
, @Repository
, and @Controller
for automatic bean detection, combined with @ComponentScan
in the configuration. For example:
@Component
public class MyService {
// Automatically registered
}
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// Automatically scans for annotated beans in the package
}
8. Conditional Bean Creation
Use annotations like @Conditional
, @ConditionalOnProperty
, or profiles (@Profile
) to conditionally create beans based on environment or other properties.
By using @Configuration
classes, you retain full control of your beans programmatically while keeping your project modular and easier to maintain.
Maven Dependencies
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.2.6</version>
</dependency>