Spring中AOP配置环绕通知

喜欢ヅ旅行 2022-11-06 03:00 279阅读 0赞

AccountServiceImpl.java(service业务层)

  1. package cn.gpxxg.service.Impl;
  2. import cn.gpxxg.service.AccountService;
  3. public class AccountServiceImpl implements AccountService {
  4. public void save() {
  5. System.out.println("保存用户");
  6. }
  7. public void edit(Integer id) {
  8. System.out.println("修改用户" + id * 2);
  9. }
  10. public int del(Integer id) {
  11. System.out.println("删除用户");
  12. return 0;
  13. }
  14. }

bean.xml(此文章中最重要的就是看它)

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:aop="http://www.springframework.org/schema/aop"
  4. xsi:schemaLocation="
  5. http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
  6. http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
  7. <bean id="accountService" class="cn.gpxxg.service.Impl.AccountServiceImpl"></bean>
  8. <!--配置loger通知类-->
  9. <bean id="loger" class="cn.gpxxg.utils.Loger"></bean>
  10. <!--配置aop-->
  11. <aop:config>
  12. <!--
  13. aop:pointcut用于配置公共的切面表达式
  14. id:用于执行唯一的id名称
  15. expression:切面表达式的内容
  16. 注意:
  17. 1、此标签写在aop:aspect标签内部时,只有当前切面使用
  18. 2、写在aop:aspect上方时,所有切面都可使用
  19. 3、不可写在aop:aspect下方,因为当前xml的约束不允许
  20. -->
  21. <aop:pointcut id="p1" expression="execution(* cn.gpxxg.service.Impl.*.*(..))"></aop:pointcut>
  22. <!--配置切面使用aop:aspect标签-->
  23. <aop:aspect id="logAdvice" ref="loger">
  24. <!--环绕通知-->
  25. <aop:around method="aroundPrintLog" pointcut-ref="p1"></aop:around>
  26. </aop:aspect>
  27. </aop:config>
  28. </beans>

Loger.java(通知类)

  1. package cn.gpxxg.utils;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. public class Loger {
  4. /**
  5. * 前置通知
  6. */
  7. public void beforePrintLog()
  8. {
  9. System.out.println("前置通知-记录日志执行!");
  10. }
  11. /**
  12. * 后置通知
  13. */
  14. public void afterReturningPrintLog()
  15. {
  16. System.out.println("后置通知-记录日志执行!");
  17. }
  18. /**
  19. * 异常通知
  20. */
  21. public void afterthrowingPrintLog()
  22. {
  23. System.out.println("异常通知-记录日志执行!");
  24. }
  25. /**
  26. * 最终通知
  27. */
  28. public void afterPrintLog()
  29. {
  30. System.out.println("最终通知-记录日志执行!");
  31. }
  32. /**
  33. * 环绕通知
  34. * 问题:当我们配置了环绕通知后,切入点方法没有执行,而环绕通知方法执行了
  35. * 分析:通过对比动态代理代码发现,动态代理的环绕通知中有明确的切入点方法调用,而我们的代码中没有
  36. * 解决:Spring为我们提供了一个接口,ProceedingJoinPoint,该接口有一个方法,此方法就明确调用切入点方法。
  37. * 该接口可以作为环绕通知的方法参数,在程序执行时,spring会为我们提供该接口的实现类供我们使用
  38. * 总结:
  39. * spring的环绕通知,就相当与spring为我们提供了一种可以在代码中手动控制增强方法何时执行的方式
  40. */
  41. public void aroundPrintLog(ProceedingJoinPoint pjp)
  42. {
  43. Object returnValue = null;
  44. try {
  45. // 获取方法执行传递过来的参数,并且增强方法
  46. Object[] args = pjp.getArgs();
  47. Integer id = (Integer) args[0] * 2;
  48. // 前置通知
  49. this.beforePrintLog();
  50. // 执行切入点方法
  51. returnValue = pjp.proceed(args);
  52. // 后置通知
  53. this.afterReturningPrintLog();
  54. } catch (Throwable throwable) {
  55. // 异常通知
  56. this.afterthrowingPrintLog();
  57. throwable.printStackTrace();
  58. } finally {
  59. // 最终通知
  60. this.afterPrintLog();
  61. }
  62. }
  63. }

LogerTest.java(测试类)

  1. package cn.gpxxg;
  2. import cn.gpxxg.service.AccountService;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. public class LogerTest {
  6. public static void main(String[] args) {
  7. ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
  8. AccountService accountService = ac.getBean("accountService", AccountService.class);
  9. accountService.edit(4);
  10. }
  11. }

发表评论

表情:
评论列表 (有 0 条评论,279人围观)

还没有评论,来说两句吧...

相关阅读

    相关 基于注解的AOP环绕通知

    基于注解的AOP环绕通知 环绕通知本质上就是环绕通知的这一个方法实现了包括前置通知、返回通知、异常通知、后置通知所有的方法的实现。与动态代理实现的方式一样(方法的内容)

    相关 spring-环绕通知 @Around 注解

    > 环绕通知:常用于做事务,事务开启,执行方法。在目标方法执行之前之后执行。 > 被注解为环绕增强的方法要有返回值,Object类型。并且方法可以包含一个Proceedin