The Spring IoC Container

The Spring IoC Container

  • Tách riêng việc thực thi một nhiệm vụ từ việc thực hiện nó
  • Làm cho việc chuyển đổi giữa các implementations dễ dàng hơn
  • Module của ứng dụng lớn hơn
  • Dễ dàng hơn trong việc test chương trình bằng cách tách một thành phần hoặc mock các dependencies của nó, cho phép chúng communicate thông qua contracts

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

  • A package-qualified class name: thông thường là các class implementations của các beans được định nghĩa
  • Bean behavioral: Trạng thái của các beans trong container(scope, lifecycle callbacks, and so forth)
  • References to other beans: Cần thiết để beans có thể work, cũng có thể được gọi là collaborators hay dependencies
  • Other configuration settings: ví dụ như số lượng connections trong beans để quản lý connection pool hoặc size limit của pool.

<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>

public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}

<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>

public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
private DefaultServiceLocator() {}
public ClientService createClientServiceInstance() {
return clientService;
}
}

public class TraditionalStore {
private Item item;
public TraditionalStore(){
item = new ItemImplOne();
}
}

public class DIStore {
private Item item;
public DIStore(Item item){
this.item = item;
}
}

@Configuration
public class StoreConfiguration {
@Bean
public Item itemOne(){
return new ItemImplOne();
}
@Bean
DIStore store(){
return new DIStore(itemOne());
}
}

<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>

public class Store {
// the Store has a dependency on the Item
private Item item;
// setter method so that the Spring container can inject a Item
public void setItem(Item item) {
this.item = item;
}
}

<bean id="item" class="org.khoa.nguyen.dang.di.Item" />
<bean id="store" class="org.khoa.nguyen.dang.di.Store">
<property name="item" ref="item"></property>
</bean>

public class AutowiredStore {
@Autowired
private Item item;
}

  • Vi phạm Single Responsibility Principle: Bởi vì dễ dàng sử dụng nên các developers thường khai báo hàng tá các dependencies vào trong 1 class và nó vô tình vi phạm vào Single Responsibility Principle(Một class chỉ nên làm một nhiệm vụ duy nhất)
  • Sử dụng reflection để cấu hình bean cũng có nghĩa là chúng ta sẽ tốn resource hơn so với constructor và setter DI
  • No: giá trị mặc định — không sử dụng autowiring cho bean, chúng ta phải chỉ rõ tên của các dependencies
  • byName: Autowiring được thực hiện dựa vào tên của thuộc tính, Spring container sẽ tìm kiếm 1 bean name có sẵn có name trùng với name của thuộc tính
  • byType: Autowiring được thực hiện dựa vào kiểu của thuộc tính, Spring container sẽ tìm kiếm 1 bean có loại giống với loại của thuộc tính. Nếu có nhiều hơn 1 bean cùng loại, Spring sẽ throw 1 exception
  • constructor: Autowiring sẽ dựa trên constructor arguments meaning. Spring container sẽ tìm kiếm beans mà có type giống như type của constructor arguments

@Bean(autowire = Autowire.BY_TYPE)
public class Store {
private Item item;
public setItem(Item item){
this.item = item;
}
}

public class Store {
@Autowired
private Item item;
}

public class Store {
@Autowired
@Qualifier("item1")
private Item item;
}

<bean id="store" class="org.khoa.nguyen.dang.di.Store" autowire="byType" />

<bean id="itemTwo" class="org.khoa.nguyen.dang.di.ItemImplTwo" />
<bean id="storeOne" class="org.khoa.nguyen.dang.di.Store" autowire="byName" />

<bean id="item" class="org.khoa.nguyen.dang.di.ItemImplTwo" lazy-init="true"></bean>

  • ApplicationContext được tạo và khởi tạo với configuration metadata mà các beans được định nghĩa ở đó. Các configuration metadata có thể là XML, Java code, hay annotations.
  • Từng bean, các dependencies của chúng ở dạng properties, constructor arguments, hay static-factory-method sẽ được cung cấp cho bean khi khởi tạo(Spring container sẽ khởi tạo các dependencies bean trước)
  • Mỗi property hay argument constructor là một definition value để có thể set vào hay refer tới một bean khác
  • Mỗi property hay constructor argument là một value được convert từ định dạng của nó. Mặc định Spring sẽ convert một giá trị được cung cấp ở dạng String format thành built-in type như là int, String, long, boolean, etc