目录
1、什么是Spring AOP
1.1、什么是AOP
1.3、AOP与Spring AOP的关系
2、AOP的组成
2.1、切面(Aspect)
2.2、连接点(Join Point)
2.3、切点(Pointcut)
2.4、通知(Advice)
通知分类:
3、Spring AOP实现步骤
3.1、添加Spring AOP依赖
3.2、定义切面(创建切面类)
3.3、定义切点(配置拦截规则)
切点表达式说明:
3.4、定义通知的实现
4、Spring AOP实现原理
4.1、织入
4.2、动态代理
JDK和CGLIB实现的区别:
4.3、原理:
官方回答:
AOP(Aspect Oriented Programming):面向切面编程,它是一种思想,是对某一件事情的集中处理。
看不懂没关系,继续往下看~
举例说明:
例如我们要实现一个用户登录权限的校验,如果不使用AOP,我们就需要在所有的页面中都要各自实现或者调用用户登录验证的方法(出登录和注册页面不需要),而使用AOP后,我们只需要在某一处配置一下,就可以实现所有需要判断用户登录验证的地方进行用户登录验证了,不再需要每个方法中都写相同的用户登录验证了~
AOP是一种思想,而Spring AOP是一个框架,提供了一种对AOP思想的实现,他们的关系类似于IoC和DI
以下四部分:
官方回答:
切面(Aspect)由切点(Pointcut)和通知(Advice)组成,它既包含了横切逻辑的定义,也包括了连接点的定义
通俗理解:
在程序中就是一个处理某方面具体问题的一个类。类里面包含了很多方法,这些方法就是切点和通知
官方回答:
应用执行过程中能够插入切面的一个点,这个点可以是方法调用时,抛出异常时,甚至是修改字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为
通俗理解:
可能会触发AOP规则的所有点(所有请求)
也就是说,你要告诉AOP他要拦截哪些请求,例如上述的例子,你要告诉程序,除了登录和注册其他的请求都需要验证用户是否登录~
官方回答:
Pointcut是匹配Join Point的谓词
Pointcut的作用就是提供一组规则(使用AspectJ pointcut expression language来描述)来匹配Join Point,给满足规则的Join Point添加Advice
通俗理解:
用来进行主动拦截的规则(配置)
官方理解:
在AOP术语中,切面的工作被称之为通知
通知:定义了切面是什么,何时使用,其描述了切面要完成的工作,还解决何时执行这个工作的问题
通俗理解:
程序中被拦截请求触发的具体动作(做什么事),就是在通知中实现具体的业务代码。
通知分类:
AOP具体的执行动作:
创建Spring Boot项目,然后在Maven仓库中搜索AOP,添加依赖:
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect //告诉序程序,这个一个切面类
@Component//随着框架的启动,面也要启动~
public class UserAspect {
}
/**
* 切点(配置拦截规则)
*/
@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
public void pointcut() {
}
切点表达式说明:
AspectJ支持三种通配符
切点表达式由切点函数组成,其中executio()是最常用的切点函数,用来匹配方法,
语法为:execution(<修饰符><返回类型><包.类.方法(参数)><异常>)
/**
* 前置通知
*/
@Before("pointcut()")
public void beforeAdvice() {
System.out.println("执行了前置通知");
}
/**
* 后置通知
*/
@After("pointcut()")
public void afterAdvice() {
System.out.println("执行了后置通知");
}
这样看代码,看不懂的哦?我们看一下我的目录
我们再捋一捋:
我们在UserController类中,写两个方法,测试一下:
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/hi")
public String sayHi() {
System.out.println("执行了目标方法,sayHi()方法");
return "hi,老朋友~";
}
@RequestMapping("/hello")
public String sayHello() {
System.out.println("执行了目标方法,sayHello()方法");
return "hello,新朋友!!!";
}
}
程序运行起来,前端:
后端控制台:
前端:
控制台:
咱们加一个类,当这个类不被拦截时:
@RestController
@RequestMapping("/art")
public class ArticleController {
@RequestMapping("/hi")
public String sayHi() {
System.out.println("hi,hi,看到我了吗?");
return "hi,hi,看到我了吗?";
}
}
程序运行,前端:
控制台:
说明AOP是起作用了的~
再看一个环绕通知,其他的和前置通知和后置通知一样我就不举例啦~
@Around("pointcut()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("进入环绕通知");
Object obj = joinPoint.proceed();//执行目标方法
System.out.println("退出环绕通知");
return obj;
}
前端:
控制台:
前置小知识:
织入(Weaving):代理的生成时机
织入是把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点被织入到目标对象中
在目标对象的生命周期里有多个点可以进行织入:
此种实现在设计模式上称为动态代理模式,在实现的技术手段上,都是在class代码运行期,动态的织入字节码
Spring框架中的AOP,主要基于两种方式:JDK和CGLIB的方式。这两种方式的代理目标都是被代理类中的方法,在运行期,动态的织入字节码生成代码类
JDK和CGLIB实现的区别:
Spring AOP是构建在动态代理基础上的,因此Spring 对AOP的支持局限于方法级别的拦截
Spring AOP支持JDKProxy和CGLIBProxy方式实现动态代理。默认情况下,对于非final修饰的类,Spring AOP会基于CGLIBProxy生成代理类,CGLIBProxy生成代理类的原理就是继承目标类,被关键字final修饰的类,由于不能被继承,所以会基于DKProxy生成代理类
Spring AOP的本质就是生成一个目标对象的代理类,当前端传来请求时,不会将请求直接交给目标对象,而是首先代理类进行代理,如果满足一定的条件,才会将请求交给目标对象
如果处理请求前需要登录验证,那么代理类会去验证用户账号是否登录,如果用户登陆了才会将请求交给目标对象并执行核心业务代码,否则代理类之间返回响应让用户先登录~
好啦~本期到这了就结束咯~晚安!!!