Spring @Primary Annotation Example

In this short article, we’ll discuss Spring’s @Primary annotation which was introduced with Spring version 3.0 of the framework.
 
We use @Primary annotation to give higher preference to a bean when there are multiple beans of the same type.

YouTube Video - @Primary Annotation

Spring @Primary Annotation Example

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

Create a Simple Maven Project

Create a simple maven project using your favorite IDE and refer below section for packaging structure. If you are new to maven then 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 required 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</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>learn-spring-framework</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.0.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.6</version>
        </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 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 = {"[email protected]", "[email protected]", "[email protected]"};

        return emails;
    }
}

PosgreSQLDataSource.java

Let's create 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 = {"[email protected]", "[email protected]", "[email protected]"};

        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 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:
[email protected]
[email protected]
[email protected]
The source code of this article is available on my GitHub repository https://github.com/RameshMF/spring-core-tutorial

Related Spring and Spring Boot Annotations

Comments