Mục lục
Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu @Qualifier annotation trong Spring để xem nó giúp chúng ta giải quyết vấn đề gì trong Spring framework.
Ngoài ra chúng ta cũng tập trung làm sáng tỏ sự khác nhau giữa @Primary annotation và autowrire by name trong spring vì chúng đều được sử dụng để hỗ trợ tiêm các phụ thuộc.
Phân biệt Autowired annotation với @Qualifier
@Autowired annotation được sử dụng để tiêm một phụ thuộc trong spring, trong đa số trường hợp thì sử dụng @Autowrired annotation là đủ để spring hiểu và tiêm phụ thuộc cần thiết. Tuy nhiên vẫn có một số trường hợp @Autowired không vẫn chưa đủ giúp Spring hiểu.
Mặc định, Spring sẽ tìm kiếm các phụ thuộc được chú thích bởi @Autowired theo kiểu dữ liệu. Nếu có nhiều hơn một bean có cùng một kiểu dữ liệu được tiêm trong spring container, Spring sẽ ném ra một NoUniqueBeanDefinitionException.
Giả sử trong đoạn mã bên dưới
@Component("fooFormatter") public class FooFormatter implements Formatter { public String format() { return "foo"; } } @Component("barFormatter") public class BarFormatter implements Formatter { public String format() { return "bar"; } } @Component public class FooService { @Autowired private Formatter formatter; }
Chúng ta có đến 2 bean có cùng kiểu Formatter trong spring container. Như vậy, trong FooService tiêm Formatter bean với @Autowired sẽ gây ra NoUniqueBeanDefinitionException. Điều này xảy ra vì Spring không biết nên sử dụng bean nào để tiêm vào FooService, để giải quyết vấn đề này chúng ta cần chỉ định rõ hơn về 1 trong 2 bean cần sử dụng. @Qualifier được sinh ra để giải quyết vấn đề này.
@Qualifier annotation
Bằng cách sử dụng @Qualifier annotation, chúng ta có thể chỉ định rõ bean nào được sử dụng khi có nhiều bean có cùng kiểu dữ liệu.
Quay lại ví dụ trước, chúng ta có thể giải quyết vấn đề bằng cách sử dụng @Qualifier với tên bean được sử dụng trong FooService.
public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter; }
Lưu ý, để sử dụng được @Qualifier chúng ta cần sử dụng @Component với tên được chỉ định trong các implement class của Formatter interface khi có nhiều hơn 1 bean có cùng kiểu dữ liêu.
@Qualifier vs @Primary
@Primary trong Spring cũng được sử dụng để giải quyết vấn đề tương tự như @Qualifier là chỉ định bean nào được sử dụng trong trường hợp có nhiều hơn 1 bean tồn tại trong spring container.
Khi có nhiều hơn một bean có cùng kiểu dữ liệu trong spring container được định nghĩa, chúng ta có thể sử dụng @Primary annotation trên một bean, bean này sẽ được sử dụng trong các trường hợp chúng ta không chỉ định bean cụ thể.
Giả sử có 2 Employee bean được định nghĩa trong @Configuration class.
@Configuration public class Config { @Bean public Employee johnEmployee() { return new Employee("John"); } @Bean @Primary public Employee tonyEmployee() { return new Employee("Tony"); } }
Trong ví dụ trên, Spring sẽ sử dụng tonyEmployee bean trong trường hợp chúng ta sử dụng @Autowired được tiêm 1 Employee bean mà không chỉ định cụ thể. Như vậy @Primary được sử dụng với mục đích ngầm hiểu rằng bean được chú thích bởi @Primary là default bean.
Cần lưu ý rằng nếu cả @Primary và @Qualifier được sử dụng thì @Qualifier sẽ được ưu tiên sử dụng. Về cơ bản, @Primary đơn giản chỉ là trường hợp mặc định, còn @Qualifier là chỉ định cụ thể.
Chúng ta cũng có thể sử dụng @Primary cùng với @Component để chỉ ra bean mặc định, ngoài cách sử dụng nó trong @Configuration class
@Component @Primary public class FooFormatter implements Formatter { //... } @Component public class BarFormatter implements Formatter { //... }
@Qualifier vs Autowired by name
Một cách khác để xác định bean cần được sử dụng khi có nhiều hơn 1 bean tồn tại trong Spring container đó là sử dụng autowired by name.
Hãy xem ví dụ sau:
public class FooService { @Autowired private Formatter fooFormatter; }
Trong đoạn mã trên, Spring sẽ hiểu và sử dụng FooFormatter bean vì tên biến chúng ta đặt tương tự với tên class. Nếu sử dụng autowired by name thì chúng ta không cần thiết phải sử dụng @Qualifier, tuy nhiên mình khuyến khích nên sử dụng @Qualifier vì nó giúp chúng ta tránh các lỗi thiếu xót hơn.
Kết bài
Qua bài biết trên, chúng ta đã biết cách sử dụng @Qualifier annotation để giải quyết trong trường hợp có nhiều hơn 1 bean được định nghĩa. Bên cạnh @Primary và autowired by name thì @Qualifier vẫn được khuyến khích sử dụng hơn vì tính rõ ràng mà nó mang lại.
Nguồn
https://www.baeldung.com/spring-qualifier-annotation