Spring AOP 与 AspectJ

简介: 前言Spring AOP 主要具有三种使用方式,分别是注解、XML 配置、API,目前在 Spring 中,由于 XML 需要大量配置,注解已经逐步取代 XML 配置,而 API 需要对 Spring 底层具有较深入的了解才能使用,因此注解成了应用 Spring 的首选方式。

前言


Spring AOP 主要具有三种使用方式,分别是注解、XML 配置、API,目前在 Spring 中,由于 XML 需要大量配置,注解已经逐步取代 XML 配置,而 API 需要对 Spring 底层具有较深入的了解才能使用,因此注解成了应用 Spring 的首选方式。在 Spring AOP 中,Spring 又使用了 AspectJ 的注解,既然 Spring 单独提出一个 AOP 模块,那它为什么自己不提供一套注解?Spring AOP 和 AspectJ 又有何不同呢?本篇将尝试对这两者的区别与联系进行解释说明。


AspectJ 入门


既然 Spring AOP 使用到了 AspectJ 的注解,那么就有必要对 AspectJ 做一个初步的认识。


首先 AspectJ 是对 AOP 实现的框架,如果你对 AOP 的基础概念不太熟悉,可以参阅《从代理到 AOP,如何实现一个 AOP 框架?》。AspectJ 提供了独有的语法,通过自己的编译器对语法进行分析,然后将相关逻辑织入到目标类的字节码中。


1. 依赖引入


在 maven 项目中,可以引入 aspectj-maven-plugin 插件,这个插件会在编译时使用 AspectJ 的编译器。

    <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.11</version>
                <dependencies>
                    <!-- 升级 AspectJ -->
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.9.6</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <!-- 打印编织信息 -->
                    <showWeaveInfo>true</showWeaveInfo>
                    <!-- 配置 JDK 版本号 -->
                    <source>1.8</source>
                    <target>1.8</target>
                    <complianceLevel>1.8</complianceLevel>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!-- 使用这个目标来编织所有的主类 -->
                            <goal>compile</goal>
                            <!-- 使用这个目标来编织所有的测试类 -->
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>


AspectJ 编译器会在生成的字节码中加上 AspectJ 自身的注解及相关类,因此还需要引入 aspectjrt 依赖。


        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.6</version>
        </dependency>


2. AspectJ 示例


同样以日志打印为例,我们希望打印出目标方法的执行参数及返回内容。

public interface IService {
    String doSomething(String param);
}
public class ServiceImpl implements IService {
    @Override
    public String doSomething(String param) {
        return "param is : " + param;
    }
}


AspectJ 同时支持 .aj 文件和在 Java 类中使用注解,注解的使用方式与在 Spring AOP 中相同,我们创建一个 ServiceAspect.aj 文件,内容如下。


public aspect ServiceAspect {
    private Logger logger = LoggerFactory.getLogger(getClass());
    pointcut executionPointcut():execution(String IService.doSomething(String));
    before():executionPointcut(){
        logger.info("before:param is:{}", thisJoinPoint.getArgs());
    }
    after() returning(String result):executionPointcut(){
        logger.info("after returning:result is:{}", result);
    }
}


这里定义了一个 Aspect,和 Java 类相似,这里的关键字是 aspect,AspectJ 编译器会将这个文件编译为一个同名的类。


同时声明了一个名为 executionPointcut 的 Pointcut,以便 advice 复用,executionPointcut 拦截 IService.doSomething 方法的执行。


我们还在 Aspect 中定义了两个 Advice,这两个 Advice 指定了上述定义的 Pointcut,它们会在目标方法执行前后执行,然后分别打印目标方法的参数和返回值。


编写一个测试类。


public class App {
    public static void main(String[] args) {
        IService service = new ServiceImpl();
        service.doSomething("hello,aspectj");
    }
}


代码执行如下。


17:43:58.493 [main] INFO com.zzuhkp.blog.aspectj.ServiceAspect - before:param is:hello,aspectj
17:43:58.506 [main] INFO com.zzuhkp.blog.aspectj.ServiceAspect - after returning:result is:param is : hello,aspectj


成功拦截到目标方法的执行。


Spring AOP 设计目标


除了方法执行时拦截,AspectJ 还可以对字段、构造器等 Joint Point 进行拦截,作为一个专业的 AOP 框架来说功能更为强大。Spring 为什么又提出一个 AOP 框架呢?下面看下 Spring AOP 的设计目标。


Spring AOP 与大多数其他 AOP 框架有所不同,它并没有提供最完整的 AOP 实现。Spring AOP 的目标是提供 AOP 和 IOC 之间的紧密继承,以帮助解决应用程序中的常见问题。Spring 中的 Aspect 是使用普通的 bean 语法配置的,这是它和其他 AOP 实现的关键区别。Spring AOP 能解决大多数问题,对于 Spring AOP 不能解决的问题,使用 AspectJ 是最佳的选择。


Spring AOP 认为 AspectJ 是一个优秀的框架,它不与 AspectJ 竞争以提供全面的 AOP 解决方案,而是和 AspectJ 互补。Spring 将 Spring AOP 和 IOC 与 AspectJ 无缝集成,如果用户不喜欢使用 AspectJ 的注解,还可以通过 XML 配置来使用 Spring AOP。


Spring AOP 与 AspectJ 有何异同


根据前面的部分大致对这两者的不同做一个总结。


AspectJ 是一个完整的 AOP 实现,依赖特定的编译器和语法,在编译期织入字节码来实现 AOP。

Spring AOP 非完整 AOP 实现,Spring AOP 目的是为了和 IOC 容器整合,仅可选的提供了对 AspectJ 注解的支持,通过运行时创建目标类的代理来实现 AOP。


目录
相关文章
|
16天前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
76 25
|
16天前
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
69 24
|
1月前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
|
1月前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
83 8
|
3月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
111 5
|
3月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
62 5
|
3月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
3月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
72 4
|
3月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
105 8
|
3月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用