当前位置: 首页 > news >正文

【苍穹外卖Day3】AOP落地与boot配置文件

我的仓库

目录

公共字段自动填充

核心思想:

2.aop切面类实现

1️⃣ AOP 拦截

2️⃣ 获取方法参数(即实体对象)

joinPoint.getArgs() 获取的是哪个方法的参数?

3️⃣ 反射查找实体的 setter 方法并调用

4️⃣ 根据操作类型区分

🧩 JoinPoint 是什么?

小结

文件上传功能

在实际开发中,项目通常会运行在不同环境中:

Spring Boot 提供了 多环境配置文件机制(Profile) 来自动切换这些配置。

怎么读取这些配置?

小结

多表查询(逻辑外键与动态sql)


从今天开始主要是回顾外卖项目,因为已经写完在写点评了。所以就写写博客回顾回顾,还是有很多有用的东西的。

公共字段自动填充

在实际开发中,我们的实体类(POJO)通常会分为三类:

  • DTO(Data Transfer Object):用于接收前端传来的数据;

  • VO(View Object):用于向前端返回展示的数据;

  • Entity(实体类):用于与数据库表一一对应。

在外卖项目中,实体类往往包含一些相同的通用字段,比如 createTime(创建时间)、updateTime(修改时间)、createUser(创建人)、updateUser(修改人)等。这些字段几乎出现在每一张表中,如果在每次插入或更新数据时都手动去设置,不仅代码冗余,还容易遗漏或出错。

我们需要一种机制——公共字段自动填充,让这些通用字段在插入或更新时能够被框架自动处理。这样可以统一管理公共字段逻辑,保持代码的简洁性和一致性,也方便后期的维护。

实现:

  1. 核心思想:

    用自定义注解标记需要自动填充的字段,然后在执行 save / update 方法时,通过 AOP 切入点拦截这些方法,在执行

    前动态为目标对象设置字段值。

    //自动填充,标注那个类需要添加切面
    //元注解(定义注解的注解)
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AutoFill {//    这样在使用 @AutoFill 注解时,必须传入一个 OperationType 枚举值
    //    ,用于标识该方法需要什么类型的操作(比如插入、更新等)。OperationType value();
    }

    OperationType 是一个枚举类 用来标注当前方法是那种类型。

    @AutoFill(OperationType.INSERT)void adddish(Dish dish);

2.aop切面类实现

@Aspect
@Component//交给ioc管理
@Slf4j
public class AutoFillAspect {/** 切入点**:匹配任意返回值类型。
com.sky.mapper.*:匹配 com.sky.mapper 包下的所有类。
*:匹配所有方法名。
(..):匹配任意参数(数量和类型不限)* *///通配符@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.Annoation.AutoFill)")public void pointCut() {}//前置通知,再插入或更新前执行//括号里是切入点@Before("pointCut()")//连接点(下面括号里)public void Before(JoinPoint joinPoint) throws InvocationTargetException, IllegalAccessException {log.info("Before method invoked.");//获取被拦截方法的一些信息//方法签名对象MethodSignature Signature  = (MethodSignature) joinPoint.getSignature();AutoFill autoFill= Signature.getMethod().getAnnotation(AutoFill.class);OperationType operationType= autoFill.value();Object[] args = joinPoint.getArgs();//获取所有参数,约定第一个参数是实体if(args==null || args.length==0){return;}//不知道具体类型 用Object来定义实体Object arg = args[0];//数据LocalDateTime now = LocalDateTime.now();Long currentId= BaseContext.getCurrentId();//统一赋值if(operationType==OperationType.INSERT){try {Method setCreatTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdatTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);setCreatTime.invoke(arg,now);setUpdatTime.invoke(arg,now);setCreateUser.invoke(arg,currentId);setUpdateUser.invoke(arg,currentId);} catch (NoSuchMethodException e) {throw new RuntimeException(e);}}else if(operationType==OperationType.UPDATE){try {Method setUpdatTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);Method setUpdateUser = arg.getClass().getDeclaredMethod("setUpdateUser", Long.class);setUpdatTime.invoke(arg,now);setUpdateUser.invoke(arg,currentId);} catch (NoSuchMethodException e) {throw new RuntimeException(e);}}}}

解释:

  • execution(* com.sky.mapper.*.*(..))
    表示匹配 com.sky.mapper 包下所有类的所有方法,不管方法名、返回值或参数类型。

  • && @annotation(com.sky.Annoation.AutoFill)
    表示只有带有 @AutoFill 注解的方法才会被拦截。
    这样能确保 AOP 只作用于那些明确声明需要自动填充的 SQL 方法。

1️⃣ AOP 拦截

@Aspect + @Before("pointCut()")

这意味着:
在执行 Mapper 层(com.sky.mapper.*)中、带有 @AutoFill 注解的方法前,
会自动执行 Before() 这个方法。


2️⃣ 获取方法参数(即实体对象)
joinPoint.getArgs() 获取的是哪个方法的参数?

👉 获取的是当前被拦截的目标方法(也就是匹配切点的那个方法)的参数。
在上面的例子中,它获取的就是 EmployeeMapper.insert(Employee employee) 的参数。


3️⃣ 反射查找实体的 setter 方法并调用
Method setCreateTime = arg.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class); 
setCreateTime.invoke(arg, now);

getDeclaredMethod() 是反射的一部分,它会在运行时根据名字和参数类型查找方法。
invoke() 则是执行这个方法,也就是动态地调用 setter 给字段赋值。

这部分就是通过反射给对象设置:

  • createTime

  • updateTime

  • createUser

  • updateUser


4️⃣ 根据操作类型区分
  • 如果是 INSERT → 同时赋值创建和更新时间

  • 如果是 UPDATE → 只更新更新时间和更新人

🧩 JoinPoint 是什么?

JoinPoint(连接点)是 Spring AOP 提供的一个接口对象,
当你的切面方法(比如 @Before)被触发时,Spring 会自动把当前被拦截的方法相关的信息都封装到 JoinPoint 里。

它包含了:

  • 被调用的方法信息(方法名、参数、注解、所在类等)

  • 目标对象(即真正被调用的对象,比如你的 Mapper)

  • 方法参数

  • 调用位置(类名、包名等)

小结

这是我首次接触AOP思想的落地,就算在做过了之后再来看时我还是对aop的种种内容有所生疏,之后我会去好好看看spring部分!


文件上传功能

这里重点就是阿里云oss的配置,一步步来就好。

这里只多写一下boot中配置文件。

在实际开发中,项目通常会运行在不同环境中:

环境说明举例
dev开发环境本地运行、调试用
test测试环境提测、联调用
prod生产环境正式上线
Spring Boot 提供了 多环境配置文件机制(Profile) 来自动切换这些配置。

#application-dev.yml(开发环境)
aliyun:oss:endpoint: oss-cn-shanghai.aliyuncs.combucket-name: sky-takeout-devaccess-key-id: your-dev-key-idaccess-key-secret: your-dev-key-secret#application-prod.yml(生产环境)
aliyun:oss:endpoint: oss-cn-beijing.aliyuncs.combucket-name: sky-takeout-prodaccess-key-id: your-prod-key-idaccess-key-secret: your-prod-key-secret#application.yml(主配置)
spring:profiles:active: dev # 激活开发环境

当你在本地运行项目时,Spring Boot 会自动加载:application.yml + application-dev.yml

怎么读取这些配置?

定义一个配置类接收:

@Component
@ConfigurationProperties(prefix = "aliyun.oss")
@Data
public class OssProperties {private String endpoint;private String bucketName;private String accessKeyId;private String accessKeySecret;
}

Spring Boot 会自动根据当前环境加载对应的配置并注入。
你在 OSS 上传服务里只要注入它:

@Service
public class OssService {@Autowiredprivate OssProperties ossProperties;
}

小结

这就是boot配置文件的优势,可以在不同环境之间丝滑切换。

多表查询(逻辑外键与动态sql)

这里就不过多阐述了,只说一下逻辑外键的必要性。

在复杂系统中,真实外键会导致性能下降、无法分库分表、限制数据迁移并带来级联删除风险。
逻辑外键通过由应用层控制关联关系,既能保证数据逻辑一致,又提高系统的灵活性和扩展性。

唯一弊端就是我们要自己实现多表查询了哈哈哈。

http://www.dtcms.com/a/517133.html

相关文章:

  • 基于python的仓库管理系统
  • 网站短期技能培训娄底seo
  • 网站开发需求文档prd模板万网虚拟机怎么做两个网站
  • vue3使用pinia封装存储数据
  • 菜谱网站 源码可以做烟的网站吗
  • digiCamControl,一款免费开源的专业级 DSLR 远程控制工具
  • 广州网站建设提供商重庆手机网站推广报价
  • CyberSecEval数据集:全面评估大型语言模型安全性的基准测试工具
  • C++文件操作
  • 网站设计三把火科技杭州做网站建设
  • 酒店行业的网站建设制作网站南京
  • 谈谈环境变量
  • Java 序列化和Scala的闭包的区别和注意点
  • 莘庄做网站视频直播怎么赚钱的
  • 南昌网站seo公司电商网站的功能
  • 注销之后logonui.exe依然有事情要做
  • 短租网站那家做的好处富力海外网络推广
  • 【C++ STL 深入解析】insert 与 emplace 的区别与联系(以 multimap 为例)
  • 文件系统LittleFS
  • day16_接口加强练习
  • 潍坊中脉网站建设公司做个网站多少钱一个月
  • PHP+Ajax网站开发典型实例3d建模自学
  • 雪崩阵列中的多域物理串扰模型
  • 注册公司网站模版怎么自己做网页
  • 四网合一的网站个人网站可以做推广吗
  • 做网站是用wordpress还是DW谷歌海外推广怎么做
  • 蛋白表达系统的技术布局与应用
  • C++11 核心新特性:从语法重构到工程化实践
  • C# 上传票据文件 调用Dify的API完成OCR识别
  • 交换机Super密码配置方法(V7