知識庫 / Spring RSS 訂閱

Spring @Primary 註解

Spring
HongKong
5
01:44 PM · Dec 06 ,2025

1. 概述

本快速教程將討論 Spring 框架中引入的 @Primary 註解,該註解是在框架版本 3.0 中引入的。

簡單來説,我們使用 @Primary 來為同一類型的多個 Bean 提供更高的優先級。

讓我們更詳細地描述一下問題。

2. 為什麼需要@Primary

在某些情況下,我們需要註冊相同類型的多個Bean。

在本例中,我們有JohnEmployee()TonyEmployee()兩種類型的Employee Bean:

@Configuration
public class Config {

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

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

Spring 在嘗試運行應用程序時會拋出NoUniqueBeanDefinitionException

為了訪問同類型的 Bean,我們通常使用@Qualifier(“beanName”) 註解。

我們將它應用於注入點,與@Autowired 結合使用。 在我們的情況下,我們選擇在配置階段的 Bean,因此@Qualifier 無法在這裏應用。 您可以通過點擊鏈接瞭解更多關於@Qualifier 註解的信息。

為了解決此問題,Spring 提供@Primary 註解。

3. 使用

下面是配置類:

@Configuration
public class Config {

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

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

我們標記了TonyEmployee() 豆,並使用@Primary註解。 Spring 會優先注入TonyEmployee() 豆,而不是JohnEmployee() 豆。

現在,讓我們啓動應用上下文並從其中獲取Employee 豆。

AnnotationConfigApplicationContext context
  = new AnnotationConfigApplicationContext(Config.class);

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

運行應用程序後:

Employee{name='Tony'}

我們可以看出,TonyEmployee() 實例在自動裝配時表現出偏好。

4. 使用 @Primary@Component

我們可以直接在 Bean 上使用 @Primary。 讓我們來看一個示例:

public interface Manager {
    String getManagerName();
}

我們有一個 Manager 接口以及兩個子類 Bean,DepartmentManager

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

以及 總經理 Bean:

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

他們都覆蓋了 getManagerName() 方法,該方法位於 Manager 接口中。請注意,我們用 GeneralManager Bean 標記了 @Primary 註解。

這次,@Primary 註解僅在啓用組件掃描時才有意義:

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

讓我們創建一個服務,用於在查找合適的 Bean 時使用依賴注入:

@Service
public class ManagerService {

    @Autowired
    private Manager manager;

    public Manager getManager() {
        return manager;
    }
}

這裏,豆子DepartmentManagerGeneralManager都符合自動裝配的條件。

由於我們標記了GeneralManager豆子為@Primary,因此它將被用於依賴注入:

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

輸出結果是“總經理”。

5. 關於 Bean 名稱的澄清

此外,在使用 @Primary 註解時,務必確保每個 Bean 名稱在上下文中是唯一的。 Spring 默認使用方法名作為 Bean 名稱。 雖然 @Primary 指示在存在歧義的情況下,應注入哪個 Bean,但它不允許同一配置類中存在同名的多個 Bean。

為了避免此類衝突,我們需要確保配置類中的每個方法都有一個唯一的名稱。 此外,我們還可以通過在 @Bean 註解中使用 name 屬性,顯式地指定名稱:

@Bean(name = "mercedesCar")
public Car car1() {
    return new Car("Mercedes");
}

@Bean(name = "bmwCar")
@Primary
public Car car2() {
    return new Car("BMW");
}

在這種情況下,Bean 的名稱分別為 mercedesCarbmwCar,以確保唯一性並避免衝突。

6. 結論

在本文中,我們學習了 Spring 的 @Primary 註解。通過代碼示例,我們展示了 @Primary 的必要性以及使用場景。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.