Spring 注解方式实现后置通知(通知需要用到Target对象的参数)及格式化时间

本文介绍如何利用AOP后置通知实现日志记录功能,通过使用JoinPoint获取目标方法参数,并展示了日期格式化的具体实现。

前例:老师留了个作业,编写后置通知,实现日志记录的功能,日志打印即可,打印内容的模板为:” 【日志-新增手表】:当前系统时间(格式:yyyy-MM-dd HH:mm:ss) 新增XXX品牌的手表,数据记录的主键为:XXX”,其中XXX为WatchService中addWatch方法的参数的属性值。

即两点:这个后置通知需要用到Target对象里的方法的参数,就这样,我就卡住了,在后置通知的类里加参数,在Target类里加参数,我企图将Target类的参数(watch)传给后置通知,但是捣鼓了半天,才发现这个思路根本行不通,我也不知道为啥,后来问了同学才知道有这么一个思路:

后置通知的切点可以传参数,比如JoinPoint   joinPoint,这个参数的方法有如下:


getTarget():获取被代理对象
由于AOP代理原理是直接添加字节码文件,不创建新的对象。所以getThis()和getTarget()获取到的是同一个对象。同动态代理,不改变原有方法的前提下,可以拓展其他方法
getArgs():获取被代理方法的参数,返回Object[]

 

所以我们可以在切面方法(即后置通知里的方法)设一个参数,JoinPoint joinPoint,然后在方法体中用joinPoint.getArgs()[0]获取Target方法的参数,即 watch 



 


下面说说时间的格式化:

1.Date date=new Date()

System.out.println("当前时间为 date:" + date);
Long time = date.getTime();
System.out.println("当前时间为 time:" + time);
String pattern = "yyyy-MM-dd HH:m:ss";
SimpleDateFormat sf = new SimpleDateFormat(pattern);
System.out.println("当前时间为 format:" + sf.format(date));

 

<think>首先,用户在询问Spring AOP中的环绕注解的返回值是什么。具体来说,用户提到了“环绕注解”,但在提供的引用中,它被称为 `@Around`。所以,我需要关注 `@Around` 注解的相关信息。 从引用中提取关键信息: - 引用[1] 描述了通知类型:`@Around` 是环绕通知,它在目标方法前后都被执行。 - 引用[2] 提供了更多细节:`@Around` 的执行时机是“环绕方法执行(最强大)”,参数支持是 `ProceedingJoinPoint`(必选参数),典型场景包括性能监控、事务管理等。它还提到,`@Around` 方法可以自定义注解增强可读性。 - 引用[5] 提到,在切面类中,可以使用 `@Around` 注解来定义增强。 现在,重点是返回值。用户问:“环绕注解的返回值是什么”,意思是 `@Around` 方法的返回值是什么类型。 在Spring AOP中,`@Around` 方法通常返回 `Object` 类型。这是因为环绕通知可以控制目标方法的执行,并且可能需要返回目标方法的返回值或一个替代值。 回忆一下: - `@Around` 方法接受 `ProceedingJoinPoint` 作为参数,这是一个接口,允许你调用 `proceed()` 方法来执行目标方法。 - `proceed()` 方法返回目标方法的返回值,类型为 `Object`。 - 因此,`@Around` 方法本身应该返回 `Object`,以便它可以返回目标方法的返回值或修改后的值。 在引用[2]中提到:`@Around` 的参数支持是 `ProceedingJoinPoint`(必选参数),并且典型场景包括性能监控、事务管理等。虽然没有直接说返回值类型,但标准实现是返回 `Object`。 此外,引用[4]中提到 `@Around` 的作用,但没有具体说返回值,但我们可以推断。 标准Spring AOP文档中,`@Around` 方法的签名通常是: ```java @Around("pointcut") public Object adviceMethod(ProceedingJoinPoint pjp) throws Throwable { // before logic Object result = pjp.proceed(); // call the target method // after logic return result; } ``` 所以,返回值类型是 `Object`。 现在,根据系统指令: - 所有行内数学表达式使用 `$...$` 格式,但这里没有数学相关内容,所以不需要。 - 独立公式单独成段,但同样不需要。 - LaTeX语法正确:不适用。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾添加引用标识,如 [^1]。 用户指令还说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但这是第一次互动,没有上一次问题。用户的问题是直接问这个。 用户说:“我想了解Spring AOP环绕注解的返回值是什么”,所以我要直接回答。 结构化回答: 1. 先简要介绍 `@Around`。 2. 解释它的返回值类型。 3. 提供示例代码(基于引用)。 4. 引用相关部分。 5. 结尾生成相关问题。 引用来源: - 引用[2] 是最相关的,因为它提到了 `@Around` 的参数和场景。 - 引用[1] 也提到。 在回答中,添加引用标识。 例如: “环绕通知(@Around)的返回值通常是 Object 类型,因为它需要返回目标方法的执行结果或自定义的返回值 [^2]。” 然后,给出示例。 最后,生成相关问题。 相关问题应该基于主题:Spring AOP,环绕通知等。 例如: 1. 如何使用 @Around 注解实现性能监控? 2. @Around 与 @Before/@After 的区别是什么? 3. 环绕通知中如何处理异常? 确保回答清晰、可靠。 完整回答框架: - 开头:直接回答问题。 - 解释:详细说明。 - 代码示例:简短代码显示。 - 结尾:生成相关问题。 </think>基于您提供的引用内容,我将为您详细解释Spring AOP中环绕注解(即`@Around`)的返回值。Spring AOP的环绕通知是最强大的通知类型,它允许在目标方法执行前后插入自定义逻辑,并完全控制方法的执行流程。以下是逐步分析: ### 1. **环绕注解(@Around)的返回值类型** - **返回值必须是 `Object` 类型**:在 `@Around` 通知方法中,返回值通常是 `Object`,原因如下: - 环绕通知需要调用 `ProceedingJoinPoint.proceed()` 方法来执行目标方法,而 `proceed()` 的返回值是目标方法的执行结果(类型为 `Object`)。因此,环绕通知必须返回 `Object` 以兼容目标方法的返回值类型。 - 您可以在环绕通知中修改目标方法的返回值(例如,添加额外处理或返回一个自定义对象),但最终返回类型必须是 `Object` 以确保类型安全。如果目标方法返回原始类型(如 `int`),Spring AOP会自动装箱为包装类(如 `Integer`)。 - 在异常处理场景中,如果目标方法抛出异常,环绕通知可以选择捕获异常并返回一个默认值或重新抛出异常[^2]。 引用来源:环绕通知参数支持 `ProceedingJoinPoint`(必选参数),并强调其返回值处理能力,典型应用于性能监控和事务管理[^2]。 ### 2. **环绕通知的签名和示例代码** - **方法签名**:`@Around` 通知方法的典型签名如下: ```java @Around("pointcutExpression") // 定义切入点表达式 public Object adviceMethod(ProceedingJoinPoint pjp) throws Throwable { // 前置逻辑(在目标方法执行前) Object result = pjp.proceed(); // 执行目标方法,返回Object类型的结果 // 后置逻辑(在目标方法执行后) return result; // 返回目标方法的返回值或修改后的值 } ``` - `ProceedingJoinPoint`:是必选参数,提供 `proceed()` 方法来调用目标方法。 - `Object result`:存储目标方法的返回值,环绕通知必须返回此值或一个替代对象。 - `throws Throwable`:允许处理目标方法可能抛出的异常。 - **完整示例**:假设一个环绕通知用于记录方法执行时间: ```java import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect @Component public class PerformanceAspect { @Around("execution(* com.example.service.*.*(..))") // 切入点表达式 public Object logExecutionTime(ProceedingJoinPoint pjp) throws Throwable { long startTime = System.currentTimeMillis(); Object result = pjp.proceed(); // 执行目标方法,获取返回值 long endTime = System.currentTimeMillis(); System.out.println("方法执行耗时: " + (endTime - startTime) + "ms"); return result; // 返回目标方法的原始返回值 } } ``` 在此示例中: - `result` 是目标方法的返回值(类型为 `Object`),环绕通知最终返回相同的值。 - 如果目标方法返回 `String`,`result` 将被强制转型为 `String`(但在通知中保留为 `Object` 以通用性处理)[^2][^5]。 引用来源:`@Around` 的核心作用是环绕方法执行,支持 `ProceedingJoinPoint` 参数,并强调返回值灵活性[^2]。 ### 3. **关键注意事项** - **返回值修改**:您可以修改 `result` 后返回一个新对象(例如,缓存结果或转换数据格式),但必须确保返回类型兼容目标方法。 - **异常处理**:如果目标方法抛出异常,环绕通知可以: - 捕获异常并返回一个默认值(如 `return "fallback";`)。 - 重新抛出异常给调用者(使用 `throw e;`)。 - **与其它通知的区别**:不同于 `@AfterReturning`(仅处理成功返回)或 `@AfterThrowing`(仅处理异常),`@Around` 覆盖整个生命周期,因此它是最灵活的通知类型[^1][^2]。 总之,Spring AOP中 `@Around` 注解的返回值始终是 `Object` 类型,这使其能够处理任意目标方法的返回值,并支持高级控制逻辑[^2][^5]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值