IoC là gì? Tìm hiểu khái niệm Inversion of Control trong Spring
Với những bạn với tiếp cận công việc developer và chưa có nhiều kinh nghiệm trong lĩnh vực này chắc hẳn đang rất hoang mang về khái niệm Inversion of Control (IoC). Để hiểu rõ thuật ngữ IoC là gì và cách áp dụng nó với Spring, bạn hãy tham khảo ngay bài viết sau đây để có được những thông tin chi tiết nhất.
IoC là gì?
IoC còn có tên gọi đầy đủ là Inversion of Control, được hiểu là một nguyên lý thiết kế ứng dụng trong công nghệ phần mềm. Kiến trúc phần mềm khi áp dụng nguyên lý thiết kế này sẽ đảo ngược quyền điều khiển so với kiểu lập trình hướng thủ tục. Nếu như trong lập trình hướng thủ tục, các đoạn mã được thêm vào sẽ gọi các thư viện thì ở IoC lại hoàn toàn khác. Những IoC container sẽ chích những dependencies khi khởi tạo bean.
IoC là gì?
Đây là khái niệm rất trừu tượng, không phải ai cũng có thể hiểu được khi mới tiếp cận và cách để bạn hiểu được nó đó là trau dồi thêm kinh nghiệm cho bản thân mình.
Một số thuật ngữ liên quan khác
Spring IoC Container là gì?
Spring IoC Container được chịu trách nhiệm bởi Interface org.springframework.context.ApplicationContext. Đồng thời, phụ trách nhiệm vụ cấu hình – configuration, cài đặt – installation và tập hợp – assembling toàn bộ object beans cho Spring IoC Container.
Spring mang đến 2 tùy chọn implementation cho ApplicationContext interface là:
-
FileSystemXmlApplicationContext và ClassPathXmlApplicationContext áp dụng cho ứng dụng độc lập
-
WebApplicationContext sử dụng cho các ứng dụng web
Dependency Injection- DI là gì?
Đây là một pattern dùng để implement IoC, các dependencies sẽ được inject vào module trong quá trình khởi tạo.
Dependency Injection – DI
Cách tạo 1 dependency object trong truyền thống như sau:
public class TraditionalStore {
private Item item;
public TraditionalStore(){
item = new ItemImplOne();
}
}
Khi sử dụng phương pháp DI, chúng ta có thể viết lại chúng như sau:
public class DIStore {
private Item item;
public DIStore(Item item){
this.item = item;
}
}
Constructor Dependency Injection
Trong đây, Spring container sẽ gọi 1 constructor cùng những arguments đại diện cho các dependencies. Chẳng hạn như ở cấu hình dưới đây:
@Configuration
public class StoreConfiguration {
@Bean
public Item itemOne(){
return new ItemImplOne();
}
@Bean DIStore store(){
return new DIStore(itemOne());
}
}
Trong đó:
-
@Configuration: là 1 class nguồn của bean đã được định nghĩa bên trong
-
@Bean: dùng để định nghĩa 1 bean trên từng method
Một ví dụ khác về cấu hình bean khi sử dụng XML configuration như sau:
<bean id=”itemOne” class=”org.khoa.nguyen.dang.di.ItemImplOne”></bean>
<bean id=”store” class=”org.khoa.nguyen.dang.di.DIStore”>
<constructor-arg type=”ItemImplOne” index=”0″ name=”item” ref=”itemOne”/>
</bean>
Field Dependency Injection
Bạn có thể sử dụng cách khác để khởi tạo 1 bean cho ứng dụng đó là thêm @Autowired như trong ví dụ dưới đây:
public class AutowiredStore {
@Autowired
private Item item;
}
Trong quá trình khởi tạo AutowiredStore, trong trường hợp không có method hoặc constructor nào để inject Item bean, thì Spring sẽ sử dụng reflection để inject Item vào trong.
Đây là cách khởi tạo 1 bean vô cùng dễ dàng, tuy nhiên nó lại tồn tại một số vấn đề nên phương pháp này không được khuyến khích sử dụng nhiều.
Lazy Initialized Bean
Ở chế độ mặc định, khi startup application, Spring container sẽ tự động khởi tạo và cấu hình toàn bộ Singleton beans. Nếu bạn không thích điều này, mà chỉ muốn khởi tạo bean khi có request, thì có thể sử dụng lazy-init attribute như sau:
<bean id=”item” class=”org.khoa.nguyen.dang.di.ItemImplTwo” lazy-init=”true”></bean>
Autowiring Dependencies
Autowiring cho phép container tự động giải quyết các dependencies giữa các beans thông qua việc kiểm tra các bean đã được định nghĩa. Có 4 loại để autowiring một bean như sau:
Autowiring dependencies trong spring
-
No
: là giá trị mặc định, nó không sử dụng autowiring cho bean mà bạn phải chỉ rõ tên của các dependencies.
-
byName
: Autowiring được thực hiện nhờ vào tên của thuộc tính. Spring container sẽ làm nhiệm vụ tìm kiếm 1 bean có sẵn trong name sao cho có name trùng với name của thuộc tính.
-
byType
: Autowiring thực hiện dựa vào kiểu thuộc tính, Spring container sẽ tìm kiếm 1 bean cùng loại với thuộc tính đó. Trong trường hợp có nhiều hơn 1 bean cùng loại, spring sẽ lập tức throw 1 exception.
-
constructor
: Autowiring dựa trên constructor arguments meaning. Spring container sẽ tìm kiếm beans có loại giống với loại của constructor arguments.
Sử dụng @Autowired annotation để tạo @Qualifer và bean byType như sau:
public class AutowiringStore {
@Autowired
@Qualifier(“itemTwo”)
private Item item;
}
Sau đó, inject bean item vào item property của storeOne bean bằng cách sau:
<bean id=”itemTwo” class=”org.khoa.nguyen.dang.di.ItemImplTwo” />
<bean id=”storeOne” class=”org.khoa.nguyen.dang.di.Store” autowire=”byName” />
Trên đây là chia về Inversion of Control – IoC là gì và một số thuật ngữ liên quan khác. Nếu bạn mới ra trường, mới đi làm mà vẫn còn cảm thấy hoang mang về những khái niệm này thì cũng đừng quá lo lắng nhé. Bởi đây đều là những thuật ngữ mà không phải ai cũng có thể hiểu nhanh chóng. Bạn cần có nhiều thời gian để tiếp cận và nghiên cứu thì mới có thể hiểu hết được về chúng.