Spring AOP笔记

Spring AOP笔记

一、认识AOP

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

要理解切面编程,就需要先理解什么是切面。用刀把一个西瓜分成两瓣,切开的切口就是切面;炒菜,锅与炉子共同来完成炒菜,锅与炉子就是切面。web层级设计中,web层->网关层->服务层->数据层,每一层之间也是一个切面。编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。

我们一般做活动的时候,一般对每一个接口都会做活动的有效性校验(是否开始、是否结束等等)、以及这个接口是不是需要用户登录。

按照正常的逻辑,我们可以这么做:

20180530172331597

这有个问题就是,有多少接口,就要多少次代码copy。对于一个“懒人”,这是不可容忍的。好,提出一个公共方法,每个接口都来调用这个接口。这里有点切面的味道了。

image-20230530145422712

虽然不用每次都copy代码了,但是,每个接口总得要调用这个方法吧。于是就有了切面的概念,我将方法注入到接口调用的某个地方(切点)。

image-20230530145738258

这样接口只需要关心具体的业务,而不需要关注其他非该接口关注的逻辑或处理。红框处,就是面向切面编程。

二、AOP中的相关概念

AOP中专业术语介绍:

  • Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
  • Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
  • Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
  • Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
  • Target(目标对象):织入 Advice 的目标对象.。
  • Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程

在网上找到的一张图,可以帮助理解以上的概念

image-20230530151326562

上AOP的代码,加深一下理解:

image-20230530153723414
@Component  //注入IOC容器
@Aspect     //声明这个类是切面,也就是被抽取出的公共部分
public class LogAspect {

    @Pointcut("execution(* com.zhou.project..*.*(..))")    //声明切点,表示该方法作为切点,注解内的路径代表切点注入的位置
    private void pointcut() {
    }

    @Before(value = "pointcut()")   //切点的前置通知
    public void before() {
        System.out.println("前置通知gogogo!");
    }

    @After(value = "pointcut()")    //切点后置通知
    public void after() {
        System.out.println("后置通知gogogo!");
    }
}

创建一个这样的类,即代表“打印日志”功能切面已经创建完毕了,接下来只需要告诉spring容器我们需要开启切面代理就可以了,所以我们需要在创建一个AspectConfig配置类就行

image-20230530154110202

@EnableAspectJAutoProxy
@Configuration
@Component
public class AspectConfig{
	//什么内容都不用写
}

这样aop切面就可以使用啦

三、Spring AOP& AspectJ AOP 的区别

AOP实现的关键在于 代理模式,代理主要分为静态代理和动态代理。静态代理的代表为
AspectJ;动态代理则以Spring AOP为代表。

  • AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
  • Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
  • Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理

JDK动态代理和CGLIB动态代理的区别

  • JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
    CGLIB代理使用字节码处理框架asm,对代理对象类的class文件加载进来,通过修改字节码生成子类。
  • JDK创建代理对象效率较高,执行效率较低;
    CGLIB创建代理对象效率较低,执行效率高。
  • JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;
    CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不能代理final修饰的类。
  • JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
     1.实现InvocationHandler接口,重写invoke()
     2.使用Proxy.newProxyInstance()产生代理对象
     3.被代理的对象必须要实现接口
  • CGLib 必须依赖于CGLib的类库,需要满足以下要求:
     1.实现MethodInterceptor接口,重写intercept()
     2.使用Enhancer对象.create()产生代理对象

CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

那么如何在这两者之间做出选择呢,总结如下:

  1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,可以强制使用CGLIB实现AOP
  2. 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

四、补充

AspectJ支持三种通配符

*:匹配任意字符,只匹配一个元素(包,类,或方法,方法参数)
..:匹配任意字符,可以匹配多个元素,在表示类时,必须和*联合使用
+:表示按照类型匹配指定类的所有类,必须跟在类名后面,如com.cad.Car+,表示继承该类的所有子类包括本身
表达式示例如下:

- execution(* com.example.demo.UserController. *(..)):匹配UserController类里的所有方法。*
- execution( * com.example.demo.UserController+.*(..)):匹配UserController类的子类包括该类的所有方法
- *execution(* com.example.demo.*.*(..)):匹配com.example.demo包下的所有类的所有方法
- execution(* com.example.demo..*.*(..)):匹配com.example.demo包下、子孙包下所有类的所有方法

- execution(* addUser(String,int)):匹配addUser方法,且第一个参数类型是String,第二个参数类型是int

Advice 的类型

  • before advice, 在 join point 前被执行的 advice. 虽然 before advice 是在 join point 前被执行, 但是它并不能够阻止 join point 的执行, 除非发生了异常(即我们在 before advice 代码中, 不能人为地决定是否继续执行 join point 中的代码)
  • after return advice, 在一个 join point 正常返回后执行的 advice
  • after throwing advice, 当一个 join point 抛出异常后执行的 advice
  • after(final) advice, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice.
  • around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是最常用的 advice.
    inal) advice`, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice.
  • around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是最常用的 advice.
  • introduction,introduction可以为原有的对象增加新的属性和方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,关于Spring AOP笔记和源码讲解,我可以给你简单介绍一下。 Spring AOPSpring框架中的一个重要模块,提供了基于代理的AOP实现。AOP(Aspect Oriented Programming)面向切面编程,是一种编程思想,它通过将横切关注点与业务逻辑分离,使得系统的关注点更加清晰,代码更加简洁易懂,同时也提高了代码的可维护性和可扩展性。 在Spring AOP中,切面(Aspect)是一个类,它包含了通知(Advice)和切点(Pointcut)。通知是在切点上执行的操作,例如在方法执行前或执行后执行一些额外的逻辑。而切点则是一个表达式,用于匹配目标对象中的方法,从而确定哪些方法会被通知所影响。 Spring AOP提供了四种通知类型,分别是: 1. 前置通知(Before advice):在目标方法执行之前执行。 2. 后置通知(After returning advice):在目标方法执行之后执行,在目标方法没有抛出异常的情况下。 3. 异常通知(After throwing advice):在目标方法抛出异常后执行。 4. 最终通知(After advice):无论目标方法是否抛出异常,最终通知都会执行。 除了通知之外,Spring AOP还提供了环绕通知(Around advice),它可以在目标方法执行前和执行后执行一些额外的逻辑,并且可以控制目标方法的执行。 在Spring AOP中,代理是通过JDK动态代理或者CGLIB字节码生成技术生成的。如果目标对象实现了接口,则使用JDK动态代理实现代理;如果目标对象没有实现接口,则使用CGLIB字节码生成技术实现代理。 在Spring AOP中,通知和切点都可以使用注解的方式来声明。例如,使用@Aspect注解声明一个切面类,使用@Before、@After、@AfterReturning、@AfterThrowing和@Around注解声明通知方法,使用@Pointcut注解声明切点表达式。 关于Spring AOP源码讲解,它的实现主要涉及到以下几个类: 1. AdvisedSupport类:封装了目标对象、切面和通知等信息。 2. ProxyFactory类:用于生成代理对象的工厂类。 3. AopProxy接口:代理对象的接口。 4. JdkDynamicAopProxy和CglibAopProxy类:实现了AopProxy接口,分别用于基于JDK动态代理和CGLIB字节码生成技术的代理对象。 以上是Spring AOP笔记和简单源码讲解,希望能对你有所帮助。如果有什么不清楚的地方,可以继续问我。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值