Bài 5: Spring AOP (Aspect-Oriented Programming)
1. Định nghĩa AOP và các khái niệm chính
Aspect-Oriented Programming (AOP) là một phương pháp lập trình cho phép tách rời các cross-cutting concerns (các mối quan tâm cắt ngang) như logging, security, và transaction management ra khỏi logic chính của ứng dụng. AOP giúp cải thiện tính modular của mã nguồn bằng cách tách riêng các chức năng không liên quan trực tiếp đến logic chính.
2. Các thành phần của AOP
Aspect: Là mô-đun của các cross-cutting concerns. Ví dụ, một aspect có thể chứa logic logging hoặc transaction management.
Join Point: Là một điểm trong quá trình thực thi chương trình, chẳng hạn như thực thi một phương thức hoặc xử lý một ngoại lệ.
Advice: Là hành động được thực hiện tại một join point cụ thể. Có nhiều loại advice như Before, After, AfterReturning, AfterThrowing, và Around.
Pointcut: Là biểu thức để chọn các join point mà một advice sẽ được áp dụng. Pointcut thường được định nghĩa bằng cú pháp AspectJ.
Weaving: Là quá trình kết hợp aspect với các đối tượng mục tiêu để tạo ra các đối tượng được quản lý bởi Spring AOP.
3. Cách cấu hình và sử dụng AOP trong Spring
3.1. Cấu hình AOP bằng XML
<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<bean id="loggingAspect" class="com.example.LoggingAspect"/>
<bean id="targetService" class="com.example.TargetService"/>
</beans>
// LoggingAspect.java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
@Before("execution(* com.example.TargetService.*(..))")
public void logBefore() {
System.out.println("Logging before method execution");
}
}
// TargetService.java
public class TargetService {
public void performTask() {
System.out.println("Performing task");
}
}
// MainApp.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
TargetService targetService = (TargetService) context.getBean("targetService");
targetService.performTask();
}
}
3.2. Cấu hình AOP bằng Java Annotations
// AppConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.example")
public class AppConfig {
@Bean
public LoggingAspect loggingAspect() {
return new LoggingAspect();
}
@Bean
public TargetService targetService() {
return new TargetService();
}
}
// LoggingAspect.java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.TargetService.*(..))")
public void logBefore() {
System.out.println("Logging before method execution");
}
}
// TargetService.java
import org.springframework.stereotype.Component;
@Component
public class TargetService {
public void performTask() {
System.out.println("Performing task");
}
}
// MainApp.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
TargetService targetService = context.getBean(TargetService.class);
targetService.performTask();
}
}