参考资料
https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&vd_source=c581024b8cd9585ec6a75c56ac05571a
1. AOP简介
- AOP 面向切面编程,一种编程范式,指导开发者如何组织程序结构。
- 作用:非侵入式的进行功能增强。
2. 核心概念
3. AOP 入门案例
- 导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
- 通知类
@Component //注入容器
@Aspect //告诉Spring这是个通知类,
public class MyAdvice {
@Pointcut("execution(* com.xin.web.service.impl.*.*(..))")
public void pt() {
}
@Before("pt()") //绑定通知和切入点
public void timeMethod() {
//通知方法
System.out.println(System.currentTimeMillis());
}
}
- 业务逻辑类
@Service("userService")
@Scope("singleton")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void save(User user) {
System.out.println("执行插入操作");
userDao.save(user);
}
@Override
public void remove() {
System.out.println("执行删除操作");
userDao.remove();
}
@Override
public void update() {
System.out.println("执行修改操作");
userDao.update();
}
@Override
public void findAll() {
System.out.println("执行查询操作");
userDao.findAll();
}
}
- Spring配置类开启注解
@Configuration //配置类
@ComponentScan("com.xin") //配置包扫描路径
@PropertySource("classpath:db.properties") //加载Properties文件
@Import({
JDBCConfig.class, MyBatisConfig.class}) //
@EnableAspectJAutoProxy //开启AOP 代理
public class SpringConfig {
}
4. AOP 工作流程
5. AOP 切入点表达式
6. AOP 通知类型
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(* com.xin.web.service.*Service.*(..))")
public void pt() {
}
@Before("pt()")
public void timeMethod() {
System.out.println("前置通知");
}
@After("pt()")
public void after() {
System.out.println("后置通知");
}
@Around("pt()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前通知");
pjp.proceed();
System.out.println("环绕后通知");
}
@AfterReturning("pt()")
public void afterReturning() {
System.out.println("方法返回后通知");
}
@AfterThrowing("pt()")
public void afterThrowing() {
System.out.println("异常后通知");
}
}
7. AOP 通知获取 参数、返回值、异常
参数
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(* com.xin.web.service.*Service.*(..))")
public void pt() {
}
@Before("pt()")
public void before(JoinPoint joinPoint) {
//获取原始类的形参
Object[] args = joinPoint.getArgs();
System.out.println(Arrays.toString(args));
}
@Around("pt()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取原始类的形参
Object[] args = proceedingJoinPoint.getArgs();
System.out.println(Arrays.toString(args));
Object result = proceedingJoinPoint.proceed(args);
return result;
}
}
返回值
只有环绕通知和返回后通知 能拿到返回值。
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(* com.xin.web.service.*Service.*(..))")
public void pt() {
}
@Around("pt()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取返回值
Object result = proceedingJoinPoint.proceed();
return result;
}
@AfterReturning(value = "pt()",returning = "result")//指定接受返回值的形参
public void afterReturning(Object result){
//原始类方法的返回值
System.out.println(result);
}
@AfterReturning(value = "pt()", returning = "result")//指定接受返回值的形参
public void afterReturning(JoinPoint joinPoint, Object result) {
//如果需要用JoinPoint,那么两个形参的顺序必须是 JoinPoint在前
//原始类方法的返回值
System.out.println(result);
}
}
异常
只有环绕通知和异常后通知有。
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(* com.xin.web.service.*Service.*(..))")
public void pt() {
}
@Around("pt()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
//获取返回值
Object result = null;
try {
result = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
//捕获原始类方法的异常
throwable.printStackTrace();
}
return result;
}
@AfterThrowing(value = "pt()",throwing = "e")//设置形参接受返回值
public void afterThrowing(Throwable e){
//原始类方法的异常
System.out.println(e);
}
}