SpringAOP是什么?为什么要有SpringAOP?
原文:SpringAOP是什么?为什么要有SpringAOP?
一、有SpringAOP之前
简单的开发场景,只需要写简单的业务逻辑,比如CRUD
但是在执行具体的逻辑之前,需要进行权限校验,或者在具体的逻辑之后,需要日志记录呢?
这样就增加了很多代码,而且增加的这些代码都是差不多的
既然如此,那我们抽出来吧!在这个类里面写一个私有的方法。
代码少了很多,但是如果其他的类也需要用到权限校验和日志记录呢?
难道也要在其他类里面写私有方法吗?这也太麻烦了。
为了解决这个问题,有两种方法。
第一种:将这个私有方法抽出来不就好了,我直接写两个工具类,一个是权限校验,一个是日志记录,谁用谁调用。
第二种:我直接搞一个父类,谁用我就让它继承这个父类,这样就能直接调用父类的方法。
但是不论是第一种还是第二种其实都会侵入业务类的方法逻辑,那么有没有一种方法,能在没有对业务核心代码侵入性的前提下,给业务核心代码添加额外的功能呢?
这时候AOP就出来了,也就是所谓的面向切面编程。
首先来看一下AOP的概念:
切入点:
想额外添加功能的方法
切面:
权限检查、日志记录等这些增强逻辑的方法在的类
通知:
在目标方法运行的什么时机来执行某个增强逻辑
目标方法前还是目标方法后
切入点表达式:
规定增强逻辑需要去增强什么方法
二、有SpringAOP之后
使用方法:
maven依赖
<dependencies><!--导入Spring Context核心依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.23</version></dependency><!--Spring AOP--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.3.1</version></dependency><!--Lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><!--Junit单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies>
切入点
package com.moon.aop.bean;/*** @Author moon* @Date 2023/10/15 15:55* @Description 切入点*/
public class UserService {public void addUser() {System.out.println("添加用户...");}public void queryUser() {System.out.println("查询用户...");}public void editUser() {System.out.println("编辑用户...");}public void deleteUser() {System.out.println("删除用户...");}
}
切面
package com.moon.aop.bean;/*
* 底层依赖Aspect的注解【但是原理不同】
* */
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;/*** @Author moon* @Date 2023/10/15 15:58* @Description 切面,里面放的增强逻辑*/@Aspect
public class UserAspect {/** 这就是传说中上文所谓的切入点表达式* */@Pointcut(value = "execution(* com.moon.aop.bean.UserService.*(..))")public void point() {}/** 这就是增强逻辑* @Before、@After就是所谓的通知* */@Before(value = "point()")public void beforeRun() {System.out.println("在目标方法执行前开始执行");}@After(value = "point()")public void afterRun() {System.out.println("在目标方法执行后开始执行");}
}
配置类:用来初始化和加载Spring的IOC容器
package com.moon.aop.bean;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;/*** @Author moon* @Date 2023/10/15 16:07* @Description 用该类来初始化和加载IOC容器*/@Configuration
public class SpringConfig {@Beanpublic UserAspect userAspect() {return new UserAspect();}@Beanpublic UserService userService() {return new UserService();}
}
Junit单元测试
import com.moon.aop.bean.SpringConfig;
import com.moon.aop.bean.UserService;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author moon* @Date 2023/10/15 16:32* @Description*/
public class AOPTest {@Testpublic void test01() {/** 通过配置类初始化IOC容器* */AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);/** 获取目标对象,Bean* */UserService userService = context.getBean(UserService.class);userService.addUser();}
}
AOP并没有生效
此时userService.getClass().getName()的值为
那是因为Spring并没有开启AOP,需要我们手动开启
package com.moon.aop.bean;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;/*** @Author moon* @Date 2023/10/15 16:07* @Description 用该类来初始化和加载IOC容器*/@Configuration
/*
* 手动开启AOP功能
* */
@EnableAspectJAutoProxy
public class SpringConfig {@Beanpublic UserAspect userAspect() {return new UserAspect();}@Beanpublic UserService userService() {return new UserService();}
}
成功!
此时userService.getClass().getName()的值为