Spring @Primary Annotation

Spring @Primary Annotation

1. обзор

В этом кратком руководстве мы обсудим аннотацию Spring@Primary, которая была представлена ​​в версии 3.0 платформы.

Проще говоря,we use @Primary to give higher preference to a bean when there are multiple beans of the same type.

Опишем проблему подробно.

2. Зачем нужен@Primary?

В некоторых случаяхwe need to register more than one bean of the same type.

В этом примере у нас есть bean-компонентыJohnEmployee() иTonyEmployee() типаEmployee:

@Configuration
public class Config {

    @Bean
    public Employee JohnEmployee() {
        return new Employee("John");
    }

    @Bean
    public Employee TonyEmployee() {
        return new Employee("Tony");
    }
}

Spring throws NoUniqueBeanDefinitionException if we try to run the application.

Для доступа к bean-компонентам одного типа мы обычно используем аннотацию@Qualifier(“beanName”).

Применяем его в точке впрыска вместе с@Autowired. В нашем случае мы выбираем bean-компоненты на этапе настройки, поэтому@Qualifier не может быть применен здесь. Мы можем узнать больше об аннотации@Qualifier, следуя заlink.

Чтобы решить эту проблему, Spring предлагает аннотацию@Primary.

3. Используйте@Primary с@Bean

Давайте посмотрим на класс конфигурации:

@Configuration
public class Config {

    @Bean
    public Employee JohnEmployee() {
        return new Employee("John");
    }

    @Bean
    @Primary
    public Employee TonyEmployee() {
        return new Employee("Tony");
    }
}

Мы помечаем компонентTonyEmployee() знаком@Primary. Spring будет вводить bean-компонентTonyEmployee() предпочтительно, а неJohnEmployee().

Теперь давайте запустим контекст приложения и получим из него bean-компонентEmployee:

AnnotationConfigApplicationContext context
  = new AnnotationConfigApplicationContext(Config.class);

Employee employee = context.getBean(Employee.class);
System.out.println(employee);

После того, как мы запустим приложение:

Employee{name='Tony'}

From the output, we can see that the TonyEmployee() instance has a preference while autowiring.

4. Используйте@Primary с@Component

We can use @Primary directly on the beans. Давайте посмотрим на следующий сценарий:

public interface Manager {
    String getManagerName();
}

У нас есть интерфейсManager и два подкласса beans,DepartmentManager:

@Component
public class DepartmentManager implements Manager {
    @Override
    public String getManagerName() {
        return "Department manager";
    }
}

И bean-компонентGeneralManager:

@Component
@Primary
public class GeneralManager implements Manager {
    @Override
    public String getManagerName() {
        return "General manager";
    }
}

Оба они отменяютgetManagerName() интерфейсаManager. Также обратите внимание, что мы помечаемGeneralManager bean с помощью@Primary.

На этот раз@Primary only makes sense when we enable the component scan:

@Configuration
@ComponentScan(basePackages="org.example.primary")
public class Config {
}

Давайте создадим сервис, который будет использовать внедрение зависимостей при поиске нужного bean-компонента:

@Service
public class ManagerService {

    @Autowired
    private Manager manager;

    public Manager getManager() {
        return manager;
    }
}

Здесь оба beansDepartmentManager andGeneralManager подходят для автоматического подключения.

As we marked GeneralManager bean with @Primary, it will be selected for dependency injection:

ManagerService service = context.getBean(ManagerService.class);
Manager manager = service.getManager();
System.out.println(manager.getManagerName());

На выходе будет «General manager”..

5. Заключение

В этой статье мы узнали об аннотации Spring@Primary. На примерах кода мы продемонстрировали необходимость и варианты использования@Primary.

Как обычно, доступен полный код этой статьиover on GitHub project.