Spring - @Primary Annotation Example

In this quick article, we’ll discuss Spring’s @Primary annotation which was introduced with version 3.0 of the framework.
Simply put, we use @Primary to give higher preference to a bean when there are multiple beans of the same type.
Let’s describe the problem in detail.

Why is @Primary Needed?

In some cases, we need to register more than one bean of the same type.
In this example we have mySQLConnection() and oracleConnection() beans of the Connection type:
@Configuration
public class Config {
 
    @Bean
    public Connection mySQLConnection() {
        return new MySQLConnection();
    }
 
    @Bean
    public Connection oracleConnection() {
        return new OracleConnection();
    }
}
Spring throws NoUniqueBeanDefinitionException if we try to run the application.
To access beans with the same type we usually use @Qualifier(“beanName”) annotation.
We apply to at the injection point along with @Autowired. In our case, we select the beans at the configuration phase so @Qualifier can’t be applied here. We can learn more about @Qualifier annotation by following the link.
To resolve this issue Spring offers the @Primary annotation. The following example shows how to use @Primary annotation in a spring application.
The @Primary annotation may be used on any class directly or indirectly annotated with @Component or on factory methods annotated with @Bean. In this example, we will use @Primary annotation with @Component annotation.

Spring @Primary Annotation Example

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

Tools and technologies used

  • Spring Framework - 5.1.0.RELEASE
  • JDK - 8 or later
  • Maven - 3.2+
  • IDE - Eclipse Mars/STS

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

Below diagram shows a project structure for your reference -

The pom.xml File

<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>net.javaguides.spring</groupId>
    <artifactId>spring-primary-annotation</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-scope-example</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
     <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>5.1.0.RELEASE</version>
       </dependency>
    </dependencies>
    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
           <plugins>
              <plugin>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <version>3.5.1</version>
                  <configuration>
                      <source>1.8</source>
                      <target>1.8</target>
                  </configuration>
              </plugin>
           </plugins>
     </build>
</project>
Next, consider the following MessageService interface.

MessageService.java

package net.javaguides.spring.primary;

public interface MessageService {
 public void sendMsg(); 
}
Create three beans named as FacebookMessageService, EmailMessageService, and TwitterMessageService, which implement the MessageService interface.

FacebookMessageService.java

package net.javaguides.spring.primary;

import org.springframework.stereotype.Component;

@Component
public class FacebookMessageService implements MessageService {
    @Override
    public void sendMsg() {
        System.out.println("FacebookMessageService implementation here");
    }
}

EmailMessageService.java

package net.javaguides.spring.primary;

import org.springframework.stereotype.Component;

@Component
public class EmailMessageService implements MessageService {

    @Override
    public void sendMsg() {
        System.out.println("EmailMessageService Implementation here");
    }
}

TwitterMessageService.java

package net.javaguides.spring.primary;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

@Primary
@Component
public class TwitterMessageService implements MessageService {
    @Override
    public void sendMsg() {
        System.out.println("TwitterMessageService Implementation here");
    }
}
Note that in the above TwitterMessageService class we have added @Primary with @Component annotation.

Annotation Based Configuration - AppConfig.java

package net.javaguides.spring.primary;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "net.javaguides.spring.primary")
public class AppConfig {
 
}

Running Spring Application - Application.java

Let's create a main class and run an application.
package net.javaguides.spring.primary;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MessageService messageService = context.getBean(MessageService.class);
        messageService.sendMsg();
        context.close();
    }
}

Output

TwitterMessageService Implementation here
The source code of this article is available on my GitHub repository https://github.com/RameshMF/spring-core-tutorial



Comments