Spring @Primary Annotation Example

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.

Spring @Primary Annotation Example

Let's create an example to demonstrate the use of @Primary annotation in a spring application.

Create a Simple Maven Project

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.

Project Structure

The below diagram shows a project structure for your reference -

The pom.xml File

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>
    
    

DataSource.java

Let's create a DataSource interface and the below content to it:


    package com.spring.core.assignment;

    public interface DataSource {
        String[] getEmails();
    }

MySQLDataSource.java

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;
        }
    }

PosgreSQLDataSource.java

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.

EmailService.java

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.

Annotation-Based Configuration - AppConfig.java


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 {
}
            

Running Spring Application - Application.java

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();
    }
}
            

Output:


ramesh@gmail.com
tony@gmail.com
john@gmail.com