文章目录
- Spring AOP简介
- 例子
Spring AOP简介
Spring AOP
(Aspect-Oriented Programming)是 Spring 框架中的一个核心模块,用于实现面向切面编程
。它提供了一种将横切关注点(cross-cutting concerns)与核心业务逻辑分离的机制。
在传统的面向对象编程中,我们通常按照功能模块对代码进行划分,比如将业务逻辑、数据访问、日志记录等功能分别封装在不同的类中。然而,某些功能可能会跨越多个模块,比如日志记录、事务管理、权限控制等,这就是所谓的横切关注点。横切关注点的存在会导致代码的重复性
增加,降低了代码的可维护性和灵活性。
Spring AOP 提供了一种通过将横切关注点从核心业务逻辑中抽离出来,并在特定的执行点(如方法调用、方法执行前后、异常抛出等)插入切面(Aspect)的方式来解决这个问题。通过 AOP,我们可以将这些横切关注点封装到独立的切面中,然后在需要的地方将这些切面织入到应用程序中,而无需修改核心业务逻辑的代码。
例子
当你需要在 Spring Boot 项目中实现公共字段自动填充时,可以使用 Spring AOP 来简化开发。以下是实现这一目标的步骤:
-
自定义注解 AutoFill:
- 创建一个自定义注解
AutoFill
,用于标识需要进行公共字段自动填充的方法。这些方法通常是 Mapper 中涉及到插入
和更新
的方法。 - 在
AutoFill
注解中,指定数据库操作类型(INSERT 或 UPDATE)。
- 创建一个自定义注解
-
自定义切面类 AutoFillAspect:
- 创建一个切面类
AutoFillAspect
,用于统一拦截加入了AutoFill
注解的方法。 - 在切面中,通过反射为公共字段赋值。
- 切面应该定义
切入点
(拦截哪些请求)和通知
(对拦截的请求进行额外的代码补充与增强)。
- 创建一个切面类
-
在 Mapper 的方法上加入 AutoFill 注解:
- 在需要进行公共字段自动填充的 Mapper 方法上加入
AutoFill
注解。 - 根据操作类型(INSERT 或 UPDATE),自动填充相应的字段值。
- 在需要进行公共字段自动填充的 Mapper 方法上加入
具体实现步骤如下:
-
自定义注解 AutoFill:
package com.hac.annotation; import com.hac.enumeration.OperationType; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AutoFill { OperationType value(); // 自己定义一个枚举类OperationType。数据库操作类型:UPDATE 或 INSERT }
-
自定义切面 AutoFillAspect:
package com.hac.aspect; import com.hac.annotation.AutoFill; import com.hac.constant.AutoFillConstant; import com.hac.context.BaseContext; import com.hac.enumeration.OperationType; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.time.LocalDateTime; // 切面类 @Aspect @Component @Slf4j public class AutoFillAspect { // 切点 // 这个切点表达式表示匹配 com.hac.mapper 包及其子包下的所有类的所有方法,并且这些方法被 @AutoFill 注解标注 // 当匹配到这些连接点时,与该切点关联的切面(Aspect)中定义的通知(Advice)就会被触发,执行相应的切面逻辑。 @Pointcut("execution(* com.hac.mapper.*.*(..)) && @annotation(com.hac.annotation.AutoFill)") public void autoFillPointCut() {} // 通知 @Before("autoFillPointCut()") public void autoFill(JoinPoint joinPoint) { // JoinPoint 是连接点,表示被拦截的方法。 // 获取到当前被拦截的方法上的数据库操作类型 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); AutoFill autoFill = method.getAnnotation(AutoFill.class); // 根据操作类型为公共字段赋值 if (autoFill.value() == OperationType.INSERT) { // 设置 createTime、updateTime、createUser、updateUser // ... } else if (autoFill.value() == OperationType.UPDATE) { // 设置 updateTime、updateUser // ... } } }
-
在 Mapper 的方法上加入 AutoFill 注解:
package com.hac.mapper; import com.hac.annotation.AutoFill; import com.hac.enumeration.OperationType; import org.apache.ibatis.annotations.Mapper; @Mapper public interface YourMapper { @AutoFill(OperationType.INSERT) void insertData(YourEntity entity); @AutoFill(OperationType.UPDATE) void updateData(YourEntity entity); }
基于 Spring AOP 实现公共字段自动填充,涉及到了一些 AOP 相关的术语。让我来详细解释一下这些术语:
-
切面类(Aspect):
- 切面类,横切关注点的模块化
- 在公共字段自动填充的场景中,切面负责拦截加入了
AutoFill
注解的方法,并在方法执行前后进行功能增强。
-
切点(PointCut):
- 指定了哪些方法会被拦截【切点表达式定义了何时应该激活切面】
- 在公共字段自动填充的流程中,切点是指加入了
AutoFill
注解的方法。
-
通知(Advice):
- 通知是切面中的具体逻辑代码,用于在切点位置执行特定的操作。通知则指定了在那些点应该执行的操作。【拦截的方法执行前,先执行通知】
- 在公共字段自动填充的场景中,通知负责根据操作类型(INSERT 或 UPDATE)为公共字段赋值。
总之,Spring AOP 提供了一种灵活且强大的方式来增强应用程序的功能,同时保持代码的整洁和可维护性。