Post

Spring Dependency Injection

1. Giới thiệu

IoC (Inversion of Control): Đảo ngược điều khiển, nó giúp làm thay đổi luồng điều khiển của chương trình một cách linh hoạt. Thường dùng với Denpendency Injection.

IoC Container được xem là cốt lõi của Spring Framework, giúp lập trình viên quản lý quá trình thực thi DI (Dependency Injection) trong ứng dụng một cách tự động.

Trong Spring, Spring Container (IoC Container) sẽ tạo các đối tượng, lắp rắp chúng lại với nhau, cấu hình các đối tượng và quản lý vòng đời của chúng từ lúc tạo ra cho đến lúc bị hủy.

Spring Container sử dụng Denpendency Injection để quản lý các thành phần, đối tượng để tạo nên một ứng dụng. Các thành phần, đối tượng này gọi là Spring Bean.

IoC Container trong Spring có 2 kiểu là: BeanFactoryApplicationContext. Cả hai đều là các interface thực hiện IoC Container. ApplicationContext được xây dựng BeanFactory nhưng nó có thêm một số chức năng mở rộng như tích hợp với Spring AOP, xử lý message, context cho web application.

2. Demo

  • Ví dụ demo với BeanFactory

Khai báo thư viện spring-bean như sau:

1
2
3
4
5
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>4.3.13.RELEASE</version>
</dependency>

Lớp HelloWorld.java:

1
2
3
4
5
6
7
8
9
10
11
public class HelloWorld {
	private String message;

	public void setMessage(String message) {
		this.message = message;
	}

	public void getMessage() {
		System.out.println("Print : " + message);
	}
}

Cấu hình file xml để tạo đối tượng HelloWorld thông qua IoC Container:

1
2
3
4
5
6
7
8
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   <bean id = "helloWorld" class = "springframework..springioc.beanfactory.HelloWorld" >
      <property name = "message" value = "Hello World!"/>
   </bean>

Việc cuối cùng là tạo BeanFactory để đọc cấu hình và tạo ra đối tượng HelloWorld.

1
2
3
4
5
6
7
8
// tạo factory    
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// đọc thông tin file cấu hình và gán vào factory
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("beans.xml"));
//tạo đối tượng từ factory
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
  • Ví dụ demo với Application Context

Khai báo thư viện spring-context

1
2
3
4
5
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.13.RELEASE</version>
</dependency>

Một lớp DataResource.java chứa thông tin kết nối tới database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class DataResource {
	private String driverClassName;
	private String url;
	private String username;
	private String password;

	public String getDriverClassName() {
		return driverClassName;
	}

	public void setDriverClassName(String driverClassName) {
		this.driverClassName = driverClassName;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void printConnection() {
		System.out.println("url: " + this.url + "\n" + "username/password: " + this.username + "/" + this.password);
	}
}

Để tạo đối tượng HelloWorld thông qua IoC container ta sẽ cấu hình nó trong file applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  <bean id="dataResource" class="springframework.springioc.applicationcontext.DataResource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost/database_name" />
    <property name="username" value="root" />
    <property name="password" value="admin1234" />
  </bean>
</beans>

Tạo một đối tượng ApplicationContext để lấy thông tin từ file cấu hình và tạo đối tượng DataResource

1
2
3
4
5
public static void main(String[] args) {
  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  DataResource obj = (DataResource) context.getBean("dataResource");
  obj.printConnection();
}

Trong hai ví dụ trên, với BeanFactory hay Application Context nếu bạn muốn thay đổi messge trong đối tượng HelloWorld, hay database của bạn thay đổi username/password hay bạn đổi kết nối sang database khác bạn chỉ cần đổi lại thông tin trong file xml là đã thay đổi được luồng chạy của chương trình, đó chính là IoC.

3. Spring Bean

Spring Bean là các object trong Spring Framework, được khởi tạo thông qua Spring Container. Bất kỳ class Java POJO nào cũng có thể là Spring Bean nếu nó được cấu hình và khởi tạo thông qua container bằng việc cung cấp các thông tin cấu hình (các file config .xml, .properties..)

Có 5 scope được định nghĩa cho Spring Bean:

  • Singleton: Chỉ duy nhất một thể hiện của bean sẽ được tạo cho mỗi container. Đây là scope mặc định cho spring bean. Khi sử dụng scope này cần chắc chắn rằng các bean không có các biến/thuộc tính được share.
  • Prototype: Một thể hiện của bean sẽ được tạo cho mỗi lần được yêu cầu(request)
  • Request: giống với prototype scope, tuy nhiên nó dùng cho ứng dụng web, một thể hiện của bean sẽ được tạo cho mỗi HTTP request.
  • Session: Mỗi thể hiện của bean sẽ được tạo cho mỗi HTTP Session
  • Global-Session: Được sử dụng để tạo global sesion bean cho các ứng dụng Portlet.

Bạn cũng có thể tự định nghĩa các scope cho riêng mình, tuy nhiên các scope cung cấp bởi spring dùng tốt và đáp ứng hầu hết các trường hợp. Để thay đổi Scope của các bean bạn có thể định nghĩa nó trong file xml, hoặc các annotation:

1
2
3
<bean id="helloWorld1" class="springframework.di.HelloWorld" scope="your scope">
    <property name="message" value="Hello World" />
</bean>

Hoặc

1
2
3
4
5
@RestController
@Scope("prototype")
public class SpringBeanController{
	
}

Spring Framework cung cấp ba cách để cấu hình bean được sử dụng trong ứng dụng.

  • Annotation Based Configuration – Bằng việc sử dụng @Service hoặc @Component annotations. Chi tiết về Scope có thể được cung cấp bởi @Scope annotation.
  • XML Based Configuration – Bằng việc tạo file XML Spring Configuration để config beans. Nếu bạn sử dụng Spring MVC framework, config dựa trên xml có thể được load tự động bằng việc viết một bài code boiler plate trong web.xml.
  • Java Based Configuration – Đươc tích hợp từ Spring 3.0, chúng ta có thể configure Spring beans sử dụng chương trình java. Một vài annotations quan trọng được sủ dụng cho config dựa trên java là @Configuration, @ComponentScan@Bean.

Spring IoC và Bean là hai khái niệm nền tảng quan trọng làm cơ sở tiến sâu hơn trong quá trình tìm hiểu và làm việc với Spring. Hãy thận trọng và cẩn thận lưu lại những gì có thể để làm bàn đạp cho bước tiến sau này bạn nhé – vì còn nhiều điều nhứt nhói và đau đầu lắm.

Bài viết mang tính chất “ghi chú, lưu trữ, chia sẻ và phi lợi nhuận”.
Nếu bạn thấy hữu ích, đừng quên chia sẻ với bạn bè và đồng nghiệp của mình nhé!

Happy coding! 😎 👍🏻 🚀 🔥

Đọc thêm:

This post is licensed under CC BY 4.0 by the author.