锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 软件开发
  3. JAVA
  4. SpringBoot通过3种方式实现AOP切面

SpringBoot通过3种方式实现AOP切面

0
  • JAVA
  • 发布于 2024-08-16
  • 0 次阅读
黄健
黄健

本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net

❃博主首页 : 「码到三十五」 ,同名公众号 :「码到三十五」,wx 号 : 「liwu0213」
☠博主专栏 : <mysql 高手> <elasticsearch 高手> <源码解读> <java 核心> <面试攻关>
♝博主的话 : 搬的每块砖,皆为峰峦之基;公众号搜索「码到三十五」关注这个爱发技术干货的 coder,一起筑基

文章目录

      • 前言
      • 1. 使用动态代理实现 AOP
      • 2. 使用 Java Agent 技术实现 AOP(AspectJ Weaver)
      • 3. 使用 AspectJ 编译时织入实现 AOP
      • 总结

前言

Spring,SpringBoot 框架凭借多种高效机制,显著增强了代码的功能性,并实现了切面编程(AOP)的精髓。其核心亮点之一,是运用动态代理技术,无需触动源代码即可在 Bean 的运行时为其动态织入额外功能,如日志记录、安全验证等,从而实现非侵入式的代码增强。

此外,Java Agent 技术,以 AspectJ Weaver 为代表,在 JVM 层面上大显身手,拦截类加载过程并动态修改类字节码。这一技术不仅拓展了 AOP 的应用场景,还蕴含了巨大的性能优化潜力,为开发者提供了更多元化的 AOP 实现方式。

AspectJ-Maven-Plugin 编译插件则采取了另辟蹊径的方法。它在编译阶段直接对源代码或字节码进行修改,确保切面逻辑与业务代码的无缝融合。这种方式不仅优化了程序的性能,还大幅减少了运行时的开销,为复杂的业务逻辑提供了坚实的支撑。

1. 使用动态代理实现 AOP

定义:AOP 是一种编程范式,用于将横切关注点(如日志、安全、事务管理等)从业务逻辑中分离出来,形成独立的模块。这样可以减少代码的冗余,提高代码的可维护性和模块性。

特点:

  • 关注点分离:将横切关注点与业务逻辑分离。
  • 提高代码复用:横切关注点可以被多个地方复用。
  • 减少代码冗余:避免了在多个地方重复编写相同的代码。

通过动态代理方式,只需要在项目中定义 @Aspect 切面即可完成增强逻辑, 利用 CGLIB 生成了代理类。

切面类代码:

@Aspect
@Component
public class LoggingAspect {

    // 定义切点
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayerExecution(){}

    // 在切点方法执行前执行
    @Before("serviceLayerExecution()")
    public void logBeforeServiceMethod(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }

    // 可以继续添加其他类型的通知,如@After、@AfterReturning、@AfterThrowing、@Around等
}

服务类代码:

@Service
public class UserService {
    public void save() {
        System.out.println("Saving user...");
    }
}

2. 使用 Java Agent 技术实现 AOP(AspectJ Weaver)

定义:Java Agent 技术允许开发者在 JVM 层面拦截类加载过程,动态修改类字节码。这种技术通过 Java Instrumentation API 实现。

应用场景:

  • AOP 支持:利用 Java Agent 技术(如 AspectJ Weaver),可以在 JVM 层面拦截类加载过程,动态修改类字节码,实现更广泛的 AOP 支持。
  • 性能优化:通过动态修改字节码,可以优化类的执行性能。
  • 动态监控与调试:在类加载时注入监控或调试代码。

特点:

  • 广泛支持:支持在 JVM 层面进行类加载的拦截和修改。
  • 配置复杂:相比其他 AOP 实现方式,配置可能更为复杂。

使用 Java Agent 技术涉及到更复杂的配置,包括编写自定义的 Agent 类,主要步骤包括将 AspectJ Weaver 作为 Java Agent 运行。下面看看aop.xml和切面类的配置。

aop.xml(放在META-INF目录下):

<aspectj>
    <weaver>
        <!-- 指定哪些包下的类需要被织入 -->
        <include within="com.example.service..*"/>
    </weaver>
    <aspects>
        <!-- 指定切面类,可定义多个 -->
        <aspect />
    </aspects>
</aspectj>

切面类代码(与动态代理类似,但不需要@Component注解):

@Aspect
public class LoggingAspect {
    // 与动态代理相同的切点和通知定义
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayerExecution(){}

    @Before("serviceLayerExecution()")
    public void logBeforeServiceMethod(JoinPoint joinPoint) {
        // 日志记录逻辑
    }
}

** 指定 JVM 参数 **
使用 Java Agent 时,需要在 JVM 启动参数中指定 AspectJ Weaver 的 jar 包

-javaagent:d:/maven/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar

通过以上实现, 我们的 SpringBoot 业务代码 UserService 被增强了,同时 UserService 并没有创建代理。通过反编译查看 UserService 编译后的字节码也没有任何的变化。Agent 的原理就在进行类加载时对类进行增强。

3. 使用 AspectJ 编译时织入实现 AOP

定义:AspectJ-Maven-Plugin 是一个 Maven 编译插件,用于在编译时直接修改源代码或字节码,以集成切面逻辑。

应用场景:

  • AOP 集成:通过编译时修改字节码,实现切面逻辑与业务代码的无缝集成。
  • 性能优化:由于是在编译阶段进行代码的增强,因此减少了运行时的开销,提升了性能。

特点:

  • 性能最佳:编译时增强减少了运行时的开销。
  • 深度集成:切面逻辑与业务代码无缝集成。
  • 需要重新编译:每当切面逻辑或业务代码发生变化时,都需要重新编译项目。

SpringBoot 中, 动态代理的方式,通过对目标类生成代理,在执行目标方法前执行增强逻辑 Advice,这种方式多少对性能是有影响的。而编译插件方式是在编译时增强,性能最佳,深度集成,减少运行时开销。

pom.xml 中添加 AspectJ-Maven-Plugin:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.11</version>
    <configuration>
        <showWeaveInfo>true</showWeaveInfo>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>com.example</groupId>
                <artifactId>your-aspect-library</artifactId>
            </aspectLibrary>
        </aspectLibraries>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal> <!-- use this goal to weave all your main classes -->
                <goal>test-compile</goal> <!-- use this goal to weave all your test classes -->
            </goals>
        </execution>
    </executions>
</plugin>

注意:如果切面类位于同一项目中,不需要单独指定aspectLibraries。

切面类代码(与动态代理相同,不需要@Component注解):

… 省略很多代码…

… 完整代码请关注博主公众号 [码到三十五] 回复 [ springboot ] 自动获取…

总结

  • AOP:是一种编程范式,用于将横切关注点从业务逻辑中分离出来,提高代码的可维护性和模块性。
  • Java Agent:在 JVM 层面拦截类加载过程,动态修改类字节码,支持广泛的 AOP 场景,但配置可能较为复杂。
  • AspectJ-Maven-Plugin:是一个 Maven 编译插件,通过编译时修改字节码来集成切面逻辑,性能最佳,但需要重新编译项目。

关注公众号 [码到三十五] 获取更多技术干货 !

标签: #软件开发 1171 #JAVA 991
相关文章

Spring 实现 3 种异步接口 2024-10-18 09:07

大家好,我是苏三~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地

重学SpringBoot3-集成Redis(五)之布隆过滤器 2024-10-08 11:24

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(五)之布隆过滤器 1. 什么是布隆过滤器? * 基本概念 适用场景 2. 使用 Redis 实现布隆过滤器 * 项目依赖 Redis 配置

SpringBoot整合异步任务执行 2024-10-08 11:24

同步任务: 同步任务是在单线程中按顺序执行,每次只有一个任务在执行,不会引发线程安全和数据一致性等 并发问题 同步任务需要等待任务执行完成后才能执行下一个任务,无法同时处理多个任务,响应慢,影响用 户体验 异步任务: 异步任务是在多线程中同时执行,多个任务可以并发执行,同时处理多个请求,响应快,资源

springboot kafka多数据源,通过配置动态加载发送者和消费者 2024-10-08 11:24

前言 最近做项目,需要支持kafka多数据源,实际上我们也可以通过代码固定写死多套kafka集群逻辑,但是如果需要不修改代码扩展呢,因为kafka本身不处理额外逻辑,只是起到削峰,和数据的传递,那么就需要对架构做一定的设计了。 准备test kafka本身非常容易上手,如果我们需要单元测试,引入ja

SpringBoot 集成 Redis 2024-10-08 11:24

一:SpringBoot 集成 Redis ①Redis是一个 NoSQL(not only)数据库, 常作用缓存 Cache 使用。 ②Redis是一个中间件、是一个独立的服务器;常用的数据类型: string , hash ,set ,zset , list ③通过Redis客户端可以使用多种语

SpringBoot整合QQ邮箱 2024-10-08 11:24

SpringBoot可以通过导入依赖的方式集成多种技术,这当然少不了我们常用的邮箱,现在本章演示SpringBoot整合QQ邮箱发送邮件…. 下面按步骤进行: 1.获取QQ邮箱授权码 1.1 登录QQ邮箱 1.2 开启SMTP服务 找到下图中的SMTP服务区域,如果当前账号未开启的话自己手动开启。

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.