Saturday, August 12, 2017

@Primary in Spring

In Spring framework, the @Primary annotation is used to give higher preference to a bean, when there are multiple beans of same type.

The @Primary annotation may be used on any class directly or indirectly annotated with @Component or on methods annotated with @Bean.

The following examples demonstrate the use of the @Primary annotation.


Consider the following User interface.

User.java

package com.boraji.tutorial.spring;

public interface User {
   public void doSomething();
}
Create two beans named as AdminUser and GuestUser, which implement the User interface.

AdminUser.java

package com.boraji.tutorial.spring;

/**
 * @author imssbora
 */
public class AdminUser implements User {

   @Override
   public void doSomething() {
      System.out.println("Inside doSomething() method of AdminUser");
   }

}
GuestUser.java

package com.boraji.tutorial.spring;

/**
 * @author imssbora
 */
public class GuestUser implements User {

   @Override
   public void doSomething() {
      System.out.println("Inside doSomething() method of GuestUser");
   }

}




Declare the AdminUser and GuestUser beans in java based configuration class.

AppConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.boraji.tutorial.spring.AdminUser;
import com.boraji.tutorial.spring.GuestUser;
import com.boraji.tutorial.spring.User;

@Configuration
public class AppConfig {
   @Bean
   @Primary
   public User getAdminUser() {
      return new AdminUser();
   }

   @Bean
   public User getGuestUser() {
      return new GuestUser();
   }
}


Now create main class and run application.

MainApp.java

package com.boraji.tutorial.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.boraji.tutorial.spring.config.AppConfig;

/**
 * @author imssbora
 */
public class MainApp {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context =
            new AnnotationConfigApplicationContext(AppConfig.class);
     
      User user=context.getBean(User.class);
      user.doSomething();
     
      context.close();
   }
}
Output

Inside doSomething() method of AdminUser
It is clear from the above output that the getAdminUser() method, annotated with @Primary, is autowired.

=============================================================

Create Component with @Primary
We have an interface and we will create two classes implementing that interface.

Animal.java
package com.concretepage;
public interface Animal {
void displayName();
}

Lion.java
package com.concretepage;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
@Primary
public class Lion implements Animal {
@Override
public void displayName() {
System.out.println("--- Lion ---");
}
}

Tiger.java
package com.concretepage;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal {
@Override
public void displayName() {
System.out.println("-- Tiger ---");
}
}


Dependency Injection
Find the class for dependency injection with @Autowired annotation.
AnimalService.java
package com.concretepage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AnimalService {
private Animal animal;
public Animal getAnimal() {
return animal;
}
@Autowired
public void setAnimal(Animal animal) {
this.animal = animal;
}
}

Configuration and Main Method
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages="com.concretepage")
public class AppConfig {
}

SpringDemo.java
package com.concretepage;
import java.sql.SQLException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringDemo {
public static void main(String[] args) throws SQLException {
   AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
   ctx.register(AppConfig.class);
   ctx.refresh();
   Animal animal = ctx.getBean(Animal.class);
   animal.displayName();
       ctx.registerShutdownHook();
}
}

Output
Case 1. As we have used @Primary annotation on Lion bean. This will be selected for dependency injection. Find the output.
--- Lion ---
 Case 2. If we do not provide @Primary annotation on any bean, we will get error.
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.concretepage.Animal] is defined: expected single matching bean but found 2: lion,tiger
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054) Case 3. If we provide @Primary annotation on both the bean, we will get error.
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.concretepage.Animal] is defined: more than one 'primary' bean found among candidates: [lion, tiger]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.determinePrimaryCandida

No comments:

Post a Comment

உப்பு மாங்காய்

சுருக்குப்பை கிழவி. சுருக்கங்கள் சூழ் கிழவி. பார்க்கும் போதெல்லாம் கூடையுடனே குடியிருப்பாள். கூடை நிறைய குட்டி குட்டி மாங்காய்கள். வெட்டிக்க...