In this short article, we’ll discuss Spring’s @Primary
annotation, which was
introduced with Spring framework version 3.0.
We use @Primary
annotation to give a higher preference for a bean when
there are multiple beans of the same type.
Let's create an example to demonstrate the use of @Primary
annotation in a
spring application.
Create a simple Maven project using your favorite IDE. Refer to the section below for the packaging structure. If you are new to Maven, read this article: How to Create a Simple Maven Project.
The below diagram shows a project structure for your reference -
Note that Spring Framework 6 requires Java 17 or later version:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0
<groupId>org.example
<artifactId>learn-spring-framework
<version>1.0-SNAPSHOT
<properties>
<maven.compiler.source>17
<maven.compiler.target>17
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework
<artifactId>spring-core
<version>6.1.8
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework
<spring-context
<version>6.1.8
</dependency>
</dependencies>
</project>
Let's create a DataSource
interface and the below content to it:
package com.spring.core.assignment;
public interface DataSource {
String[] getEmails();
}
Let's create a MySQLDataSource
class that implements the DataSource
interface and its method:
package com.spring.core.assignment;
import org.springframework.stereotype.Component;
@Component
public class MySQLDataSource implements DataSource{
@Override
public String[] getEmails() {
String[] emails = {"ramesh@gmail.com", "tony@gmail.com", "john@gmail.com"};
return emails;
}
}
Let's create a PostgreSQLDataSource
class that implements the DataSource
interface and its method:
package com.spring.core.assignment;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
@Primary
public class PostgreSQLDataSource implements DataSource{
@Override
public String[] getEmails() {
String[] emails = {"ramesh@gmail.com", "tony@gmail.com", "john@gmail.com"};
return emails;
}
}
Note that this class is annotated with @Primary
annotation and it tells
Spring Container to give higher
preference to this class while injecting using @Autowired annotation.
Next, let's create an EmailService
class and inject the PostgreSQLDataSource
bean as a dependency:
package com.spring.core.assignment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class EmailService {
private DataSource dataSource;
@Autowired
public EmailService(DataSource dataSource) {
this.dataSource = dataSource;
}
void sendEmail(){
String[] emails = dataSource.getEmails();
for(String email: emails){
System.out.println(email);
}
}
}
Note that we have annotated PostgreSQLDataSource
class with @Primary
annotation and so Spring Container
injects PostgreSQLDataSource
class as spring bean.
package com.spring.core.assignment;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.spring.core.assignment")
public class AppConfig {
}
Let's create a main class and run an application.
package com.spring.core.assignment;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
EmailService emailService = applicationContext.getBean(EmailService.class);
emailService.sendEmail();
}
}
ramesh@gmail.com
tony@gmail.com
john@gmail.com