写点什么

阿里大牛亲码 Spring AOP 详解笔记全网开源,学透并发只需 3 天

用户头像
飞飞JAva
关注
发布于: 2021 年 05 月 10 日
阿里大牛亲码 Spring AOP详解笔记全网开源,学透并发只需3天

Hello,今天给各位童鞋们分享 Spring AOP,赶紧拿出小本子记下来吧!


概述

AOP 是 aspect-oriented programming 的缩写,译为面向切面编程。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。简单来说,AOP 就是不修改源代码在主干功能里面添加新功能。

底层原理‍‍

AOP 底层使用了动态代理:在有接口的时候使用 JDK 动态代理、在没有接口的时候使用 CGLIB 字节码动态代理。

JDK 动态代理

简介

使用 JDK 动态代理需要用到 JDK 中的 Proxy 类里面的 newProxyInstance 方法创建代理对象。方法如下:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);

newProxyInstance 方法的三个参数说明:

loader 定义代理类的类加载器

interfaces 代理类要实现的接口列表(可以多个)

h 指派方法调用的处理程序(要增强的功能在这里面实现)

newProxyInstance 方法返回一个指定接口的代理类实例。

InvocationHandler 接口中有个 invoke 方法,用于实现增强的功能:

public Object invoke(Object proxy, Method method, Object[] args)


    throws Throwable;
复制代码


invoke 方法的三个参数说明:

  • proxy 表示代理对象

  • method 表示被增强的方法

  • args 是方法的参数 若没有则为 null

示例代码代码结构如下:

└─src

└─com
└─spring5
JDKProxy.java
UserDao.java
UserDaoImpl.java
复制代码

UserDaoImpl 类:


JDKProxy 类:


运行结果:

方法之前执行…add :传递的参数…[1, 2]

I am add…

方法之后执行…com.spring5.UserDaoImpl@355da254

result:3

CGLIB 字节码动态代理

简介

使用 CGLIB 字节码动态代理不受代理类必须实现接口的限制,其底层采用 ASM 字节码生成框架。CGLIB 动态代理的优缺点:

使用字节码技术生产代理类比 JAVA 反射效率高

不能对声明为 final 的方法进行代理,因为其原理是动态生成被代理类的子类

需要实现接口 MethodInterceptor,然后重写 intercept 方法:

Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable;

intercept 方法的参数说明:

  • proxy CGLIB 生成的代理类实例,也是目标对象的子类,相当于重写父类方法

  • method 被代理方法

  • args 方法参数

  • 为生成的代理类对方法的代理引用

intercept 方法返回

另外用到了 Enhancer 类,它是 Cglib 中的一个字节码增强器,先调它的 setSuperclass()将被代理类设置成父类、再调 setCallback 函数执行 intercept 方法,最后调 create()生成代理类。

示例代码

代码结构如下:

└─src

└─com
└─spring5
CglibProxy.java
User.java
复制代码


User 类:public class User {

public void sleep() {
System.out.println("我想睡觉...");
}
复制代码


}

CglibProxy 类:


运行结果:

睡觉前脱衣服

我想睡觉…

起床穿衣服

AOP 操作

概述

AOP 相关的几个术语:

  • 连接点

类里面哪些方法可以被增强,这些方法称为连接点

  • 切入点

实际被真正增强的方法称为切入点

  • 通知

实际增强的逻辑部分称为通知,分为前置通知、后置通知、环绕通知、异常通知和最终通知五种类型,其中最终通知相当于 JAVA 的 finally。

  • 切面

把通知应用到切入点过程

AspectJ

AspectJ 不是 Spring 组成部分,是一个独立的 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使 用,进行 AOP 操作。增强就是代理的意思。

准备工作

在进行 AOP 操作的时候需要先引入下面四个 Jar 包

com.springsource.net.sf.cglib-2.2.0.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

spring-aspects-5.2.6.RELEASE.jar

引入包后的所有包如下:

  • com.springsource.net.sf.cglib-2.2.0.jar

  • com.springsource.org.aopalliance-1.0.0.jar

  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

  • spring-aspects-5.2.6.RELEASE.jar

  • commons-logging-1.1.1.jar

  • spring-aop-5.2.6.RELEASE.jar

  • spring-beans-5.2.6.RELEASE.jar

  • spring-context-5.2.6.RELEASE.jar

  • spring-core-5.2.6.RELEASE.jar

  • spring-expression-5.2.6.RELEASE.jarAspectJ 的切入点表达式相关说明如下:

  • 作用

知道对哪个类里面的哪个方法进行增强

  • 语法

execution([权限修饰符] [返回类型] [类全路径] 方法名称 )

  • 示例



基于注解实现

主要步骤

主要步骤如下:

在 spring 配置文件中,开启注解扫描

  • 需要在 XML 中引入 context 和 aop 的上下文空间。

  • 使用注解创建 User 和 UserProxy 对象

  • 在增强类上面添加注解 @Aspect

  • 在 spring 配置文件中开启生成代理对象

aop:aspectj-autoproxy</aop:aspectj-autoproxy>

开启 Aspectj 生成对象后,会去代码中扫描 @aspect 注解

配置不同类型的通知

在通知方法上面使用 @Before、@AfterReturning、@Around、@AfterThrowing 和 @After 注解,结合切入点表达式配置。

@after 是在方法执行之后执行(有异常也执行),@afterReturning 是在返回值之后执行(有异常不执行)。

示例代码

代码结构:



User 类:



UserProxy 类:



Test 类:



无异常返回结果:

Around 环绕之前

前置通知 before

I am add

Around 环绕之后

最终通知 after

后置通知(返回通知)afterReturning

有异常时返回结果:

Around 环绕之前前置通知 before

最终通知 after

异常通知 afterThrowing

java.lang.ArithmeticException: / by zero

相同切入点提取用 @Pointcut 标签



多个增强类对同一个方法进行增强用 @Order 注解设置增强类优先级,数字类型值越小表示优先级越高。

@Component

@Aspect

@Order(1)

public class PersonProxy{ }

完全注解开发

在启动配置类中添加 @EnableAspectJAutoProxy 注解:

@Configuration

@ComponentScan(basePackages = { "com.spring5"})

@EnableAspectJAutoProxy(proxyTargetClass = true)

public class ConfigAop {

}

基于配置文件实现

具体步骤

  • 创建增强类和被增强类,创建相关方法

  • 在 spring 配置文件中配置两个类对象

  • 在 spring 配置文件中配置 AOP

示例代码

代码结构如下:


Student 类:


StudentProxy 类:


Test 类:


bean.xml:


运行结果:


I am before…


I want to buy a book…


I am afterReturn…


好啦,今天的文章就到这里,希望能帮助到屏幕前迷茫的你们​

​​

用户头像

飞飞JAva

关注

还未添加个人签名 2021.04.28 加入

分享、普及java相关知识

评论

发布
暂无评论
阿里大牛亲码 Spring AOP详解笔记全网开源,学透并发只需3天