๐ŸŽ‰ Special Offer !    Code: GET300OFF    Flat โ‚น300 OFF on every Java Course
Grab Deal ๐Ÿš€

Spring @Primary Annotation


Introduction

  • The @Primary annotation in Spring helps to choose one bean as the default when there are multiple beans of the same type in the Spring container.
  • It makes a bean the first choice for autowiring if no specific bean is selected using @Qualifier.

  • Placement of @Primary :
    The @Primary annotation can be applied at Class Level or Bean Definition in Configuration Class, as explained below:

    1. Class Level:
      • Mark a class as the primary bean to be used for autowiring when multiple beans of the same type exist.
      • Example:
        @Primary
        @Component
        public class PetrolEngine implements Engine
        {
            // Implementation
        }

    2. Bean Definition in Configuration Class:
      • Use @Primary on a @Bean method in a configuration class to specify the primary bean among multiple beans of the same type.
      • Example:
        @Configuration
        public class AppConfig
        {
            @Bean
            @Primary
            public Engine petrolEngine()
            {
                return new PetrolEngine();
            }
        
            @Bean
            public Engine dieselEngine()
            {
                return new DieselEngine();
            }
        }


  • Program for @Primary
    We have created the below program for @Primary annotation which is used at class level.
    Engine.java
    package in.sp.beans;
    
    public interface Engine
    {
        void start();
    }
    DieselEngine.java
    // Diesel Engine Implementation
    
    package in.sp.beans;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class DieselEngine implements Engine
    {
        @Override
        public void start() 
        {
            System.out.println("Diesel Engine started...");
        }
    }
    PetrolEngine.java
    // Petrol Engine Implementation with @Primary
    
    package in.sp.beans;
    
    import org.springframework.context.annotation.Primary;
    import org.springframework.stereotype.Component;
    
    @Component
    @Primary
    public class PetrolEngine implements Engine
    {
        @Override
        public void start()
        {
            System.out.println("Petrol Engine started...");
        }
    }
    Car.java
    package in.sp.beans;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class Car
    {
        private Engine engine;
    
        @Autowired
        public Car(Engine engine)
        {
            this.engine = engine;
        }
    
        public void drive()
        {
            engine.start();
            System.out.println("Car is running...");
        }
    }
    AppConfig.java
    // Configuration Class
    package in.sp.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan(basePackages = "in.sp.beans")
    public class AppConfig
    {
    	//no bean configuration required
    }
    MainApp.java
    package in.sp.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    import in.sp.beans.Car;
    
    public class MainApp 
    {
        public static void main(String[] args)
        {
            // Load Spring context from Java-based configuration
            ApplicationContext context = new AnnotationConfigApplicationContext(in.sp.config.AppConfig.class);
    
            // Retrieve the Car bean
            Car car = context.getBean(Car.class);
    
            // Call the drive method
            car.drive();
        }
    }
    Below is the output
    Output:
    Petrol Engine started...
    Car is running...

  • Difference between @Qualifier & @Primary :

    Aspect @Primary @Qualifier
    Scope Works globally across the application. Used at specific injection points.
    Usage Sets a default bean for injection. Explicitly selects a specific bean.
    Precedence Lower Higher