Spring Framework là một nền tảng mã nguồn mở, nhẹ và linh hoạt, cung cấp giải pháp toàn diện cho việc phát triển ứng dụng Java dựa trên kiến trúc hướng dịch vụ (SOA) và mô hình phân tầng. Dưới đây là tổng quan kỹ thuật về các thành phần cốt lõi và cách thức triển khai trong thực tế.
1. Kiến trúc tổng quan
Các lớp nền chính của Spring bao gồm:
- Một container quản lý chu kỳ sống và phụ thuộc giữa các đối tượng (Inversion of Control – IOC)
- Hệ thống trừu tượng hóa xử lý giao dịch (Transaction Abstraction)
- Lớp hỗ trợ JDBC với cơ chế xử lý ngoại lệ thông minh và quản lý tài nguyên tự động
- Tích hợp liền mạch với các framework ORM phổ biến như Hibernate, MyBatis, JPA
- Cơ chế lập trình hướng khía cạnh (Aspect-Oriented Programming – AOP) để tách rời các mối quan tâm chéo (cross-cutting concerns)
- Framework MVC linh hoạt, không ràng buộc, dễ mở rộng cho ứng dụng web
2. Thiết lập dự án Maven
Chỉ cần khai báo spring-webmvc trong pom.xml, hệ thống sẽ tự động kéo về các module phụ thuộc cần thiết:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
3. Nguyên lý IOC và DI
IOC (Inversion of Control) đảo ngược luồng điều khiển: thay vì lớp chủ động khởi tạo phụ thuộc, container chịu trách nhiệm tiêm (inject) các đối tượng đã được cấu hình sẵn. Ví dụ:
public class AccountService {
private AccountRepository repository;
// Setter injection – cách tiếp cận truyền thống
public void setAccountRepository(AccountRepository repo) {
this.repository = repo;
}
public void transfer(String from, String to, BigDecimal amount) {
repository.withdraw(from, amount);
repository.deposit(to, amount);
}
}
Khi sử dụng IOC, lớp AccountService không còn phụ thuộc trực tiếp vào cách tạo AccountRepository, giúp giảm độ gắn kết và tăng khả năng kiểm thử.
4. Cấu hình bean bằng XML
Spring hỗ trợ nhiều cách khai báo bean:
4.1 Khởi tạo qua constructor
<!-- Cách 1: Chỉ định vị trí tham số -->
<bean id="account" class="com.example.Account" c:_0="ACC-001" c:_1="10000.00"/>
<!-- Cách 2: Chỉ định theo tên tham số (yêu cầu biên dịch với -parameters) -->
<bean id="account" class="com.example.Account" c:accountId="ACC-002" c:balance="25000.00"/>
4.2 Tiêm giá trị phức tạp
<bean id="customer" class="com.example.Customer">
<property name="name" value="Nguyễn Văn A"/>
<property name="addresses">
<list>
<value>Hà Nội</value>
<value>TP.HCM</value>
</list>
</property>
<property name="preferences">
<map>
<entry key="theme" value="dark"/>
<entry key="language" value="vi"/>
</map>
</property>
</bean>
5. Tự động tiêm (Auto-wiring)
Spring hỗ trợ tự động liên kết các bean dựa trên tên hoặc kiểu dữ liệu:
autowire="byName": tìm bean cóidtrùng với tên thuộc tínhautowire="byType": tìm duy nhất một bean khớp với kiểu dữ liệu thuộc tính
Với chú thích, sử dụng @Autowired kết hợp @Qualifier để xác định rõ ràng khi có nhiều ứng viên:
@Service
public class PaymentProcessor {
@Autowired
@Qualifier("creditCardGateway")
private PaymentGateway gateway;
}
6. Quản lý phạm vi (Scope)
Phạm vi mặc định là singleton. Để tạo mới mỗi lần yêu cầu, cấu hình prototype:
<bean id="sessionManager" class="com.example.SessionManager" scope="prototype"/>
7. Cấu hình bằng Java (JavaConfig)
Thay thế hoàn toàn XML bằng lớp cấu hình thuần Java:
@Configuration
@ComponentScan("com.example.service")
public class AppConfig {
@Bean
@Scope("prototype")
public TransactionLogger transactionLogger() {
return new DatabaseTransactionLogger();
}
@Bean
public AccountService accountService() {
AccountService service = new AccountService();
service.setLogger(transactionLogger());
return service;
}
}
8. Cơ chế AOP
AOP giúp tách biệt các chức năng phụ như logging, security, transaction khỏi logic nghiệp vụ. Các thành phần cơ bản:
- Aspect: lớp chứa các advice và pointcut
- Join Point: điểm thực thi trong chương trình (ví dụ: gọi phương thức)
- Pointcut: biểu thức xác định tập hợp các join point
- Advice: hành động thực hiện tại join point (
@Before,@After,@Around)
Ví dụ sử dụng chú thích:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service..*.*(..))")
public void logMethodEntry(JoinPoint jp) {
System.out.printf("Bắt đầu thực thi: %s%n", jp.getSignature());
}
}
9. Quản lý giao dịch
Spring hỗ trợ hai mô hình:
- Declarative transaction (khuyến nghị): cấu hình qua chú thích
@Transactionalhoặc XML - Programmatic transaction: kiểm soát thủ công qua
TransactionTemplate
Cấu hình khai báo trong XML:
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="create*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.example.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
</aop:config>
10. Tích hợp với MyBatis
Sử dụng mybatis-spring để kết nối Spring với MyBatis:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
</bean>