Các cách sử dụng @Autowired annotation trong Spring

Chúng tôi rất vui mừng chia sẻ kiến thức sâu sắc về từ khóa Autowired la gi và hi vọng rằng nó sẽ hữu ích cho các bạn đọc. Bài viết tập trung trình bày ý nghĩa, vai trò và ứng dụng của từ khóa trong việc tối ưu hóa nội dung trang web và chiến dịch tiếp thị trực tuyến. Chúng tôi cung cấp các phương pháp tìm kiếm, phân tích và chọn lọc từ khóa phù hợp, kèm theo các chiến lược và công cụ hữu ích. Hi vọng rằng thông tin chúng tôi chia sẻ sẽ giúp bạn xây dựng chiến lược thành công và thu hút lưu lượng người dùng. Cảm ơn sự quan tâm và hãy tiếp tục theo dõi blog của chúng tôi để cập nhật kiến thức mới nhất.

Khởi nguồn từ Spring 2.5, framework đã giới thiệu một annotation mới @Autowired được cho phép Spring tự động hóa tìm kiếm và tiêm các bean tương ứng mà tất cả chúng ta đã khai báo trong class.

Bạn Đang Xem: Các cách sử dụng @Autowired annotation trong Spring

Trong nội dung bài viết này chúng sẽ cùng nhau tìm hiểu một số chiêu sử dụng @Autowired annotation trong Spring và phương pháp để xử lý xung đột khi có nhiều hơn một bean có thể sử dụng trong một class cụ thể.

Kích hoạt @Autowired annotation trong Spring

Spring được cho phép tự động hóa tiêm các dependency cách tự động hóa, vì vậy tất cả chúng ta chỉ việc khai báo bean bên trong các file cấu hình với @Bean annotation hay các class được chú thích với @Component annotation, Spring IoC container sẽ tự động hóa tiêm các dependency tương ứng mà tất cả chúng ta đã khai báo để sử dụng.

Ví dụ tiếp sau đây mình tạo Company bean thông qua @ComponentScan (được dùng để làm chỉ ra những nơi mà nó cần tìm những @Component class) và Address bean được đặt trong file cấu hình (được chú thích với @Configuration annotation)

@Component public class Company { private Address address; public Company(Address address) { this.address = address; } // getter, setter and other properties } @Configuration @ComponentScan(basePackageClasses = Company.class) public class Config { @Bean public Address getAddress() { return new Address(“High Street”, 1000); } }

Hơn ngoài mong đợi, với Spring Boot bạn chỉ việc sử dụng @SpringBootApplication annotation. Nó là một annotation phối hợp @Configuration, @EnableAutoConfiguration, và @ComponentScan. Thông thường nó được sử dụng với Main class trong ứng dụng Spring Boot, chỉ định cho Spring sẽ tìm kiếm các bean cùng cấp hoặc thuộc các package con của Main class.

@SpringBootApplication public class AutowiredDemoApplication { public static void main(String[] args) { SpringApplication.run(AutowiredDemoApplication.class, args); } }

Cách sử dụng @Autowired

Sau lúc các bean đã được khởi tạo và đăng ký với Spring IoC, giờ đây chúng ta có thể sử dụng @Autowired để tiêm các bean tương ứng cần sử dụng. Spring cung cấp cho tất cả chúng ta 3 phương pháp để sử dụng @Autowired annotation hoặc là chú thích trên contructor, setter hay trực tiếp trên tính chất.

@Autowired trực tiếp trên tính chất

Đây là cách sử dụng nhanh và ngắn gọn nhất, tất cả chúng ta chỉ việc chú thích @Autowired trực tiếp trên tính chất. Spring IoC sẽ tự động hóa tìm kiếm và tiêm bean tương ứng thông qua Reflection API.

Trước tiên, giả sử mình có một ExampleClassBean bean như vậy này

@Component public class FieldBean { public String getName() { return “Deft Blog”; } }

Sau đó mình tiến hành tiêm một ExampleClassBean bean vào ExampleService với @Autowired được chú thích trên tính chất.

public interface FieldExampleService { String getName(); } @Service public class FieldExampleServiceImpl implements FieldExampleService { @Autowired private FieldBean fieldBean; @Override public String getName() { return fieldBean.getName(); } }

Giờ đây, tất cả chúng ta có thể kiểm tra với mong muốn khi gọi đến getName() method sẽ nhận về giá trị “Deft Blog” như đã khai báo trước đó.

@SpringBootTest class AutowiredDemoApplicationTests { @Autowired private FieldExampleService fieldExampleService; @Test public void propertyAutowiredTest() { assertEquals(fieldExampleService.getName(), “Deft Blog”); } }

@Autowired trên setter method

Thông thường, setter method được dùng để làm khởi tạo hay update giá trị của một tính chất trong class. Này cũng là một nới lý tưởng để Spring có thể tiêm dependency vào.

Xem Thêm : Bầu khí quyển – “Hệ miễn dịch” của Trái Đất

@Component public class SetterBean { public int getValue() { return 10; } }

Giờ, mình sẽ tạo một SetterExampleService tiêm SetterBean theo phong cách setter method.

public interface SetterExampleService { int getValue(); } @Service public class SetterExampleServiceImpl implements SetterExampleService { private SetterBean setterBean; @Autowired private void setBean(SetterBean setterBean) { this.setterBean = setterBean; } @Override public int getValue() { return setterBean.getValue(); } } @Test public void setterAutowiredTest() { assertEquals(setterExampleService.getValue(), 10); }

@Autowired constructor

Cuối cùng, tất cả chúng ta có thể sử dụng @Autowired trên contructor, Spring sẽ tự động hóa tìm kiếm các bean tương ứng được khai báo như thể thông số trong constructor.

Trong ví dụ này mình sẽ sử dụng lại FieldBean và SetterBean là 2 thông số trong constructor, Spring sẽ tự động hóa tìm kiếm 2 bean này vào service để sử dụng.

@Service public class ContructorExampleServiceImpl implements ConstructorExampleService { private final FieldBean fieldBean; private final SetterBean setterBean; @Autowired public ContructorExampleServiceImpl(FieldBean fieldBean, SetterBean setterBean) { this.fieldBean = fieldBean; this.setterBean = setterBean; } @Override public String print() { return fieldBean.getName() + ” – ” + setterBean.getValue(); } }

Các chúng ta có thể chạy unit-test sau để kiểm tra kết quả

@Test public void constructorAutowiredTest() { assertEquals(constructorExampleService.print(), “Deft Blog – 10”); }

@Autowired với những optional dependency

Khi Spring không thể tìm thấy bean trong container để tiêm chúng vào nơi cần sử dụng, nó sẽ ném ra một exception khiến Khóa học không thể khởi chạy.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.autowire.sample.FooDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Để khắc phục lỗi này, tất cả chúng ta có thể sử dụng tính chất required trong @Autowired annotation chuyển nó thành FALSE, mặc định là TRUE sẽ gây ra ra lỗi khi một dependency được chú thích với @Autowired annotation không được tìm thấy.

@Service public class FieldExampleServiceImpl implements FieldExampleService { @Autowired(required = false) private FieldBean fieldBean; // …. }

Nhưng trong thực tế, cách này thường khá ít sử dụng. Thông thường, các bạn phải đảm bảo các bean được tạo đủ trong quá trình chạy ứng dụng.

Các trường lỗi khi sử dụng @Autowired

Mặc định, Spring sẽ tìm kiếm các dependency được chú thích bởi @Autowired annotation theo phong cách tài liệu. Nếu có nhiều hơn một bean có cùng kiểu tài liệu trong container nó sẽ ném ra một exception.

Để xử lý cho trường hợp xung đột này, tất cả chúng ta phải chỉ định rõ bean nào tất cả chúng ta đang cần dùng trong số những bean có cùng kiểu tài liệu đang tồn tại trong container.

@Autowired với @Qualifier

Đây là một thông dụng dùng để làm chỉ rõ bean tất cả chúng ta cần dùng trong số nhiều bean có cùng kiểu tài liệu.

Giả sử mình có một Formatter cùng với 2 bean đều implement từ nó

Xem Thêm : Lời khuyên khi sử dụng capo trong Guitar

public interface Formatter { String format(); } @Component(“bar”) public class BarFormatter implements Formatter { @Override public String format() { return “Bar”; } } @Component(“foo”) public class FooFormatter implements Formatter { @Override public String format() { return “Foo”; } }

Trong trường hợp trên, tất cả chúng ta nhiều hơn nữa 2 bean có cùng kiểu tài liệu Formatter, nên lúc mình khởi tạo ConflictServiceExample service với một dependency Formatter thì gây ra lỗi

No qualifying bean of type ‘com.deft.autowireddemo.conflict.Formatter’ available: expected single matching bean but found 2: bar,fooat org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220)

@Service public class ConflictServiceExample { @Autowired private Formatter formatter; public String format() { return formatter.format() } }

Để tránh trường hợp xung đột này, tất cả chúng ta có thể sử dụng @Qualifier để chỉ rõ tên của bean muốn sử dụng.

@Service public class ConflictServiceExample { @Autowired @Qualifier(“bar”) private Formatter formatter; public String format() { return formatter.format() } }

Autowired by name

@Autowired private Formatter formatter;

Thì có thể ngầm hiểu như

@Autowired @Qualifier(“formatter”) private Formatter formatter;

Vì trong trường hợp này, không có bean nào mang tên tương tự nên Spring chỉ tìm theo phong cách tài liệu và tìm ra được 2 bean foo và bar tương ứng.

Do vậy, các chúng ta có thể không dùng @Qualifier annotation mà chỉ việc thay thay tên tương ứng với tên của bean cần sử dụng.

Như đoạn code tiếp sau đây, mình sử dụng foo bean mà không cần sử dụng @Qualifier mà chỉ việc thay thay tên tính chất tương ứng với @Component name đã đặt trước đó (foo)

@Service public class ConflictByNameServiceExample { @Autowired private Formatter foo; public String format() { return foo.format(); } }

Kết bài

Qua nội dung bài viết này, tất cả chúng ta sẽ biết được cách sử dụng @Autowired để tiêm các dependency tự động hóa. Có tới 3 cách vận dụng @Autowired tuy nhiên, thiên hạ đồn rằng nên sử dụng constructor autowired vì nó cho tốc độ nhanh hơn là dùng field autowired phải dùng reflection để khởi tạo. Không những vậy, khi sử dụng constructor mà các thông số quá nhiều, tức thị tất cả chúng ta có thể đang vi phạm nguyên tắc SOLID vì nhiều dependency đồng nghĩa với việc class của tất cả chúng ta đang chịu trách nhiệm xử lý quá nhiều logic.

Sau rốt các chúng ta có thể xem mã nguồn mình công khai trên gitlab để chạy và kiểm thử nếu cấp thiết: autowired-demo.

Nguồn tham khảo

https://www.baeldung.com/spring-autowire

You May Also Like

About the Author: v1000