苍穹外卖day03

1.❔公共字段自动填充模块多次重复编写

⭐️解决

  • ·自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
  • 自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
  • 在Mapper的方法上加入Autoill注解

1.1💻切面与AOP

AOP 是一种编程思想(类似于 OOP 面向对象编程),
目的是将程序中与业务逻辑无关但又普遍存在的功能模块(横切关注点)分离出来,从而实现代码的高内聚、低耦合。

AOP 是一种通过“切面”技术,将横切逻辑动态织入程序运行过程中的编程思想。
“切面”是 AOP 的具体实现载体,定义了“在何处(Pointcut)”以及“做什么(Advice)”。

eg:创建人,创建时间,更新人,更新时间等需要自动填充的公共字段

[系统中所有方法调用]
         ↓ (连接点全集)
筛选出符合条件的那些方法
         ↓ (切点 Pointcut)
定义在这些方法执行前/后要做什么
         ↓ (通知 Advice)
封装成一个切面类
         ↓ (切面 Aspect)
Spring 在运行时织入增强逻辑
         ↓ (动态代理生成代理对象)

1.2连接点(jiont point)与切点(pointcut)

连接点:所有可能的拦截点【所有方法的调用】动态

切点:一种挑选连接点的规则,匹配的连接点为拦截点。静态

❔为什么【通知】传进去的参数是joint point 而非 pointcut

  • AOP包含切面+切点+通知【增强逻辑】
  • 先定义切点【规则】,接着定义通知【在调用方法上检测该方法是否满足切点定义的规则,如果满足,执行通知,该过程由SPRING AOP自动执行】,所以通知作用在切点上但是执行操作的是当前连接点。

1.3 切点的拦截路径

扫描的路径,* com.sky.mapper..(…),mapper完整的路径是sky-take-out/sky-server/mapper,当前切面的路径是sky-take-out/sky-server/aspect,为什么只写了sky.mapper就能找到呢?

因为SPRING扫描时是按照【包声明】而非物理路径,每个mapper文件上面写了声明 page com.sky.mapper.

1.4 为什么获取数据库的操作类型可以用Joinpoint.getsignature?,又为什么要把signature方法转为methodsignature接口?

一句话:在AOP里面传递信息要通过反射对象【method】

问题1:==JoinPoint== 保存了完整的上下文,包括:

  • 目标对象(target)
  • 代理对象(proxy)
  • 方法参数(args)🍁
  • 签名信息(signature)🍁
  • 当前执行点的静态和动态数据

signature里面保存的是通用签名信息,只描述方法结构,不具备反射能力

  • 方法名(getName()

  • 所属类名(getDeclaringType())【我们获取的数据库操作类型属于这一类】

  • 修饰符(getModifiers()

但是它不能拿到反射对象【method】,只有子接口MethodSignature(从上继承)能得到method对象

method对象可以

通过 getAnnotation() 获取注解;🍁本次需要的

通过 getReturnType() 获取返回类型;

通过 invoke() 执行反射调用;

通过 getParameters() 获取参数名类型等。

1.5反射对象指的就是method吗?还有其他的反射对象吗?是不是切面的通知里面想要执行增强逻辑,必须通过反射对象?

  • 反射是指是指程序在运行时能够:动态地检查类的信息;动态地调用方法;动态地修改属性;动态地创建对象。包含 ClassFieldMethodConstructor等。

  • Spring AOP 拦截的连接点(JoinPoint)主要是 方法调用, 所以绝大多数场景下我们用到的是 Method 反射对象

  • AOP执行逻辑增强有两种

    • 1.不依赖反射如打印日志

      ```java
      

      @Before(“controllerMethods()”)
      public void logStart(JoinPoint joinPoint) {
      log.info(“方法开始执行: {}”, joinPoint.getSignature().getName());
      }
      ```

    • 2.依赖反射(基于注解或方法)如动态修改执行逻辑

1.6 为什么是get annonation传入的是(AutoFill.class);

Java 一切类型(class、interface、enum、annotation)都对应一个 Class 对象,把 .class 看作是「把类型本身当作对象来使用」的语法糖。

Class c1 = User.class; // 普通类
Class c2 = Runnable.class; // 接口
Class c3 = AutoFill.class; // 注解类型
Class c4 = int.class; // 基本类型

1.7 为什么要通过反射来复制,不能直接set赋值吗?Method setCreateTime = entity.getClass().getDeclaredMethod(“setCreateTime”, LocalDateTime.class);

直接调用 entity.setXXX() 就会在编译期间执行,entity 必须是具体的实体类;
如果使用反射,这里的 entity 编译时只是一个‘占位符’,编译时只知道是object类型
当运行时根据传进来的对象动态填充,只要里面有这个方法即可调用。

反射让 AOP 的切面逻辑可以在不知道具体类型的前提下,对不同实体动态地执行相同的操作。

1.8总结component+bean+autowired与工具类实例化

工具类类型特点依赖生命周期创建方式是否需要实例化
无状态工具类所有方法静态由 JVM 类加载即可不需要 SpringNO
普通组件类/切面类有成员变量Spring 环境由 Spring 容器创建@ComponentYES
依赖外部 Bean 的工具类有成员变量Spring 环境由 Spring 容器创建@Configuration + @BeanYES

Spring 容器(IoC 容器)的本质:

管理对象(Bean)的创建、初始化、依赖关系、销毁。

所以要让对象被自动注入(@Autowired),
必须先让它进入 Spring 容器
而“进入容器”的两种主要方式就是:

  • 方式1:@Component

  • 方式2:@Configuration + @Bean


注解作用使用场景是否自动扫描是否可被注入
@Component把类交给 Spring 扫描并创建实例类本身可直接被管理(普通组件、切面、工具类等)✅ 是(通过包扫描)✅ 可被 @Autowired 注入
@Bean在配置类中手动注册一个 Bean类不能直接扫描或需要自定义构造❌ 否(需在 @Configuration 中声明)✅ 可被 @Autowired 注入
@Autowired从容器中获取 Bean 并注入到当前类依赖 Bean 的地方(Controller、Service、Util)N/A✅ 用于使用 Bean

❔2.菜品批量删除

1.调试报错:500

控制台输出:

nested exception is java.lang.IllegalStateException: No primary or single unique constructor found for interface java.util.List] with root cause

解决:1.检查mapper文件参数传递

​ 2.检查controller方法里面 @RequestParam,不加 @RequestParam → Spring 试图构造 List 对象 → 失败 → 500

public Result delete(@RequestParam List<Long> ids){}
//告诉Spring把表单参数自动转为list

总之:json格式(1,2,)用@RequesBody,query格式(地址栏格式value?)用@RequestParam

注解参数来源请求体格式常见场景
@RequestParamURL 查询参数 / 表单?ids=1&ids=2&ids=3GET、DELETE
@RequestBodyHTTP BodyJSON,例如 [1,2,3]POST、PUT、DELETE(携带 body)

❔3.菜品修改

⛏controller 里面的参数注解

  • @PathVariable : 路径参数,用于 URL 路径变量,eg @PathVariable id,根据id查询菜品/dish/{id}
  • @RequestBody:接收前端[json格式]的数据,eg { “name”: “红烧肉”, “price”: 22.5 }
  • @RequesParam:用于 URL 查询参数(多个),spring自动把表单拆分为list,eg,批量删除,从前端获取id组合,/dish?ids=1&ids=2

⛏controller 传给前端的两种Result泛型

  • VO:其他需要回显时,例如根据id查
  • PageResult:分页

⛏口味表的修改操作==先删除所有,再重新插入【因为修改有很多不确定性】

⛏就算有公共字段自动填充(自定义AOP切面类)也要再sql实现里面写对应sql语句,sql指明哪些字段需要更新,自动填充负责赋值

⛏如果(service)某项操作涉及到多个表,需要使用事务注解@Transcation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值