Spring Framework là một hệ sinh thái mã nguồn mở đóng vai trò như một "container" quản lý vòng đời của các đối tượng trong ứng dụng Java. Thay vì lập trình viên phải trực tiếp khởi tạo đối tượng, Spring đảm nhận việc này thông qua các cơ chế cốt lõi như IoC và DI.
1. Các khái niệm nền tảng
- Inversion of Control (IoC - Đảo ngược điều khiển): Đây là tư tưởng thiết kế chuyển giao quyền kiểm soát luồng chương trình và khởi tạo đối tượng từ lập trình viên sang cho framework.
- Dependency Injection (DI - Tiêm phụ thuộc): Là cách hiện thực hóa IoC, cho phép các thành phần phụ thuộc được đưa vào một đối tượng thông qua setter, constructor hoặc annotation.
2. Cấu trúc và thiết lập ban đầu
Để một ứng dụng Spring cơ bản hoạt động, bạn cần tối thiểu 4 thư viện lõi (Core Containers):
spring-beans: Quản lý các đối tượng Bean.spring-context: Cung cấp ngữ cảnh ứng dụng.spring-core: Các thành phần nền tảng của framework.spring-expression: Ngôn ngữ biểu thức SpEL.
3. Khởi tạo đối tượng với ApplicationContext
Trong Spring, ApplicationContext chịu trách nhiệm nạp cấu hình và quản lý các đối tượng. Thông thường, chúng ta sử dụng tệp XML để định nghĩa các bean này.
Ví dụ về cấu hình applicationContext.xml:
<?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.xsd">
<!-- Định nghĩa một Bean đơn giản -->
<bean id="employeeService" class="com.tech.service.EmployeeServiceImpl"></bean>
</beans>
Cách truy xuất Bean từ mã nguồn Java:
public class MainApp {
@Test
public void testSpringContext() {
// Nạp tệp cấu hình từ thư mục resources (classpath)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// Lấy đối tượng đã được Spring khởi tạo
EmployeeServiceImpl service = (EmployeeServiceImpl) context.getBean("employeeService");
System.out.println("Đối tượng đã được khởi tạo: " + service);
}
}
4. Tiêm dữ liệu phức hợp (Complex Injection)
Ngoài các kiểu dữ liệu cơ bản, Spring cho phép tiêm các cấu trúc dữ liệu như mảng (Array), danh sách (List), bản đồ (Map) và thuộc tính (Properties) một cách linh hoạt.
Định nghĩa lớp POJO chứa các tập hợp dữ liệu:
package com.tech.model;
import java.util.*;
public class AppConfigModel {
private String[] serverNodes;
private List<String> adminEmails;
private Map<String, String> databaseSettings;
private Properties metadata;
// Getter và Setter...
public void setServerNodes(String[] serverNodes) { this.serverNodes = serverNodes; }
public void setAdminEmails(List<String> adminEmails) { this.adminEmails = adminEmails; }
public void setDatabaseSettings(Map<String, String> databaseSettings) { this.databaseSettings = databaseSettings; }
public void setMetadata(Properties metadata) { this.metadata = metadata; }
@Override
public String toString() {
return "Nodes: " + Arrays.toString(serverNodes) + ", Emails: " + adminEmails;
}
}
Cấu hình tiêm giá trị cho các tập hợp trong XML:
<bean id="appConfig" class="com.tech.model.AppConfigModel">
<!-- Tiêm giá trị cho mảng -->
<property name="serverNodes">
<array>
<value>Node-01</value>
<value>Node-02</value>
</array>
</property>
<!-- Tiêm giá trị cho List -->
<property name="adminEmails">
<list>
<value>admin@example.com</value>
<value>support@example.com</value>
</list>
</property>
<!-- Tiêm giá trị cho Map -->
<property name="databaseSettings">
<map>
<entry key="url" value="jdbc:mysql://localhost:3306/db" />
<entry key="user" value="root" />
</map>
</property>
</bean>
Khi ứng dụng khởi chạy, Spring sẽ tự động phân tích cấu hình XML, sử dụng Reflection để gọi các phương thức Setter tương ứng và đưa các giá trị đã định nghĩa vào đối tượng AppConfigModel, giúp tách biệt hoàn toàn việc thiết lập dữ liệu khỏi logic nghiệp vụ của ứng dụng.