Khóa học spring-boot

@Primary annotation và @Qualifier annotation

0 phút đọc

Trong Spring Boot, khi bạn có nhiều bean cùng loại trong một ứng dụng và muốn chỉ định bean nào sẽ được ưu tiên sử dụng hoặc chọn bean cụ thể để sử dụng, bạn có thể sử dụng hai annotation quan trọng là @Primary@Qualifier. Trong bài viết này, chúng ta sẽ tìm hiểu cách sử dụng hai annotation này để quản lý các bean và giải quyết vấn đề khi có nhiều bean cùng loại trong Spring Boot.

Cài đặt

Trước khi đi vào phần thực hành, hãy đảm bảo bạn đã cài đặt các gói thư viện của Spring Boot trong Maven bằng cách thêm spring-boot-starter-parent là parent của dự án và các dependencies cần thiết. Dưới đây là một ví dụ về cách cấu hình pom.xml:

xml Copy
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

Cách @Autowired hoạt động

Trước khi tìm hiểu về @Primary@Qualifier, hãy hiểu cách @Autowired hoạt động trong Spring Boot.

Annotation @Autowired cho biết Spring Boot nên tự động inject bean tương ứng vào vị trí được đánh dấu. Ví dụ:

java Copy
@Component
public class Girl {
    @Autowired
    Outfit outfit;
}

Annotation @Autowired cũng có thể được sử dụng trên constructor hoặc method, thay vì thuộc tính, để Spring Boot tự động inject các dependency vào Class đã gọi. Ví dụ:

java Copy
@Component
public class Girl {
    Outfit outfit;

    @Autowired
    public Girl(Outfit outfit) {
        this.outfit = outfit;
    }
}
java Copy
@Component
public class Girl {
    Outfit outfit;

    public Girl() {

    @Autowired
    public void setOutfit(Outfit outfit) {
        this.outfit = outfit;
    }
}

Tuy nhiên, nếu bạn sử dụng constructor hoặc setter để tiêm phụ thuộc, @Autowired không bắt buộc.
Spring IoC Container tự động hiểu cách tiêm phụ thuộc vào constructor mà không cần @Autowired. Tuy nhiên, sử dụng @Autowired trên constructor/setter làm cho mã nguồn rõ ràng hơn và dễ đọc hơn.

Vấn đề của @Autowired trong Spring Boot

Trong thực tế, khi ứng dụng của bạn chứa nhiều bean cùng loại trong Spring context, Spring Boot có thể gặp khó khăn trong việc xác định bean nào cần được inject. Ví dụ:

java Copy
@Component
public class Bikini implements Outfit {
    @Override
    public void wear() {
        System.out.println("Mặc bikini");
    }
}

@Component
public class Naked implements Outfit {
    @Override
    public void wear() {
        System.out.println("Đang không mặc gì");
    }
}

Class Girl yêu cầu inject một Outfit.

java Copy
@Component
public class Girl {
    @Autowired
    Outfit outfit;

    public Girl(Outfit outfit) {
        this.outfit = outfit;
    }
}

Khi bạn chạy ứng dụng, Spring Boot sẽ báo lỗi:

Kết quả

Parameter 0 of constructor in spring.helloprimaryqualifier.Girl required a single bean, but 2 were found:

  • bikini: defined in file /path/to/Bikini.class
  • naked: defined in file /path/to/Naked.class

Điều này xảy ra vì Spring Boot không biết phải chọn bean nào để inject vào Girl khi có nhiều bean cùng loại trong context.

@Primary trong Spring Boot

Cách giải quyết đầu tiên là sử dụng Annotation @Primary.

@Primary đánh dấu một bean là ưu tiên và sẽ luôn được ưu tiên chọn trong trường hợp có nhiều bean cùng loại trong context.

Trong ví dụ ở trên

, nếu bạn đánh dấu Naked là primary, Spring Boot sẽ chọn Naked để inject vào Girl.

java Copy
@Component
@Primary
public class Naked implements Outfit {
    @Override
    public void wear() {
        System.out.println("Đang không mặc gì");
    }
}

@Qualifier trong Spring Boot

Cách giải quyết thứ hai là sử dụng Annotation @Qualifier.

@Qualifier xác định tên của một bean mà bạn muốn chỉ định để inject.

Ví dụ:

java Copy
@Component("bikini")
public class Bikini implements Outfit {
    @Override
    public void wear() {
        System.out.println("Mặc bikini");
    }
}

@Component("naked")
public class Naked implements Outfit {
    @Override
    public void wear() {
        System.out.println("Đang không mặc gì");
    }
}

@Component
public class Girl {
    Outfit outfit;

    @Autowired
    public Girl(@Qualifier("naked") Outfit outfit) {
        this.outfit = outfit;
    }
}

Với cách này, bạn chỉ cần xác định tên của bean bạn muốn inject vào Girl thông qua @Qualifier("naked"), và Spring Boot sẽ tìm bean có tên đó trong context để inject.

Annotation @Primary@Qualifier là hai công cụ mạnh mẽ để quản lý các bean và giải quyết vấn đề khi có nhiều bean cùng loại trong Spring Boot. Sử dụng chúng giúp bạn kiểm soát việc inject bean vào các đối tượng một cách hiệu quả trong ứng dụng của bạn.

Avatar
Được viết bởi

Admin Team

Gợi ý câu hỏi phỏng vấn

Không có dữ liệu

Không có dữ liệu

Gợi ý bài viết
Không có dữ liệu

Không có dữ liệu

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào