Spring AOP 快速入门
Aspect Oriented Programming(AOP)即面向切面编程,可以在不改变原有设计的情况下进行功能增强,如日志记录,性能统计,安全控制,事务处理和异常处理等。本文以在执行指定方法前打印当前时间为例,介绍Spring AOP的基本使用。
创建Maven项目
依赖如下
<!-- spring-context传递依赖spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
<!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
准备测试代码
定义Service接口及实现类
package com.cas.service;
public interface IUserService {
void save();
void update();
void delete();
}
package com.cas.service.impl;
import com.cas.service.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
@Override
public void save() {
System.out.println("save user");
}
@Override
public void update() {
System.out.println("update user");
}
@Override
public void delete() {
System.out.println("delete user");
}
}
初步测试
package com.cas;
import com.cas.service.IUserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.cas")
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
IUserService userService = context.getBean(IUserService.class);
userService.save();
userService.update();
userService.delete();
}
}
执行结果如下
save user
update user
delete user
AOP增强功能
首先复习下AOP相关概念,连接点(JoinPoint)是可以被切入增强的地方,切入点(PointCut)是需要被切入的连接点,通知(Advice)是需增强的通用功能,切面是把通知/增强绑定到切入点。在不改动原有代码情况下,如果想在执行delete前打印当前时间,则delete方法为切入点,打印时间操作为通知。
定义切面类,绑定切入点和通知
package com.cas.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 自定义切面类
* 使用 @Component 注册到IOC容器
* 使用 @Aspect 声明为切面类
*/
@Component
@Aspect
public class MyAspect {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//切入点
@Pointcut("execution(void com.cas.service.IUserService.delete())")
private void pointCut() {
}
//前置通知
@Before("pointCut()")
public void log() {
System.out.println(sdf.format(new Date()));
}
}
添加@EnableAspectJAutoProxy注解以启用AOP
@Configuration
@ComponentScan("com.cas")
@EnableAspectJAutoProxy
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
IUserService userService = context.getBean(IUserService.class);
userService.save();
userService.update();
userService.delete();
}
}
再次执行main方法时结果如下,可见delete方法成功被增强了
save user
update user
2022-09-07 21:27:27
delete user
最后展示一下项目结构
│ pom.xml
│
└───src
├───main
│ ├───java
│ │ └───com
│ │ └───cas
│ │ │ Application.java
│ │ │
│ │ ├───aop
│ │ │ MyAspect.java
│ │ │
│ │ └───service
│ │ │ IUserService.java
│ │ │
│ │ └───impl
│ │ UserServiceImpl.java
│ │
│ └───resources
└───test
└───java