码迷,mamicode.com
首页 > 编程语言 > 详细

spring03-aop

时间:2019-11-02 20:09:41      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:扫描   表示   inf   base   system   切面   oid   问题   编译   

spring03-AOP


  1. 术语:
    1. joinPoint(连接点):
      连接点指的是被拦截的点, 在spring中指的就是配置了动态代理的类中的所有方法
    2. pointCut(切入点):
      切入点就是被增强的方法
    3. advice(通知):
      通知指的就是增强方法具体做了什么, 实际上就是指提供了代理方法的类, 分为前置通知, 后置通知, 异常通知, 最终通知, 环绕通知
    4. introduction(引介):
      引介是一种特殊的通知. 在不修改类代码的前提下, introduction可以在运行期间为类动态的添加一些方法或field
    5. target(目标对象):
      被代理对象
    6. weaving(织入):
      指把增强应用到目标对象产生代理对象的过程.
      spring采用动态代理植入, aspectJ使用编译期织入和类装载期织入
    7. proxy(代理):
      一个类被aop织入后产生的代理对象
  2. aop的xml配置步骤
    1. 将通知类添加到spring容器
    2. 使用 aop:config 标签开始配置aop
    3. 使用 aop:aspect 标签配置切面
      1. id: 唯一标识
      2. ref: 指定通知类的bean的id
    4. 在 aop:aspect 内部使用相应标签配置通知类型
      1. 通知标签:
        • method: 指定通知方法
        • pointcut: 指定切入点表达式, 用于指定对哪些方法进行加强
          切入点表达式写法: execution(访问修饰符 返回值 全限定方法名(参数表))
          • public void cn.ann.service.AccountService.saveAccount()
          • 其中:
            1. 访问修饰符可以省略
            2. 返回值可以使用通配符, 表示任意返回值
            3. 包名可以只用通配符, 表示任意包
            4. 包名可以使用 .. 表示当前包及其子包
            5. 类名和方法名也可以使用通配符
            6. 参数表:
              • 可以直接写数据类型: 基本类型直接写名称: int; 引用类型写全限定类名
              • 可以使用通配符代表所有参数, 但是方法必须有参数才可以
              • 可以使用 .. 表示有无参数均可, 有参数可以是任意类型
          • 全通配写法: * *..*.*(..)
          • 开发中的常用写法:
            * 业务层包名..*.*(..)
            * cn.ann.service..*.*(..)
    5. 通知标签
      1. aop:before: 前置通知. 切入点执行前执行
      2. aop:after-returning: 后置通知: 切入点正常执行后执行
      3. aop:after-throwing: 异常通知: 切入点产生异常后执行
      4. aop:after: 最终通知: 切入点执行后执行(不论是否产生异常)
      5. aop:around: 环绕通知: spring为我们提供的可以 让我们手动设置通知什么时候执行 的方式
        • 方法设计:

          // spring提供了ProceedingJoinPoint接口用来让我们获取切入点的信息
          public Object aroundLogging(ProceedingJoinPoint pjp) {
              try {
                  System.out.println("前置 ...");
                  Object ret = pjp.proceed(pjp.getArgs());
                  System.out.println("后置 ...");
                  return ret;
              } catch (Throwable throwable) {
                  System.out.println("异常 ...");
                  throw new RuntimeException(throwable);
              } finally {
                  System.out.println("最终 ...");
              }
          }
      • 后置通知和异常通知只能执行一个
    6. 配置切入点

      <aop:config>
          <!-- 配置切入点 -->
          <aop:pointcut id="logPointcut" expression="execution(* cn.ann.service..*.*(..))"/>
      </aop:config>
    • aop配置代码

      <!-- 配置AOP -->
      <aop:config>
          <!-- 配置切入点 -->
          <aop:pointcut id="logPointcut" expression="execution(* cn.ann.service..*.*(..))"/>
          <!-- 配置切面 -->
          <aop:aspect id="logAdvice" ref="logger">
              <!-- 前置通知
              <aop:before method="beforeLogging" pointcut-ref="logPointcut"/> -->
              <!-- 后置通知
              <aop:after-returning method="afterReturningLogging" pointcut-ref="logPointcut"/> -->
              <!-- 异常通知
              <aop:after-throwing method="afterThrowingLogging" pointcut-ref="logPointcut"/> -->
              <!-- 最终通知
              <aop:after method="afterLogging" pointcut-ref="logPointcut"/> -->
              <!-- 环绕通知 -->
              <aop:around method="aroundLogging" pointcut-ref="logPointcut"/>
          </aop:aspect>
      </aop:config>
  3. aop注解配置
    1. 开启注解扫描
      • <context:component-scan base-package="cn.ann"/>
    2. 开启aop注解
      • <aop:aspectj-autoproxy/>
    3. 配置通知
      1. 将通知类添加到spring容器中: @Component("logger")
      2. 声明通知类: @Aspect
      3. 配置切入点:

        @Pointcut("execution(* cn.ann.service..*.*(..))")
        private void logPointcut(){}
      4. 配置通知

        @Before("logPointcut()")
        public void beforeLogging(){
            System.out.println("before logging run...");
        }
        
        @AfterReturning("logPointcut()")
        public void afterReturningLogging(){
            System.out.println("afterReturning logging run...");
        }
        
        @AfterThrowing("logPointcut()")
        public void afterThrowingLogging(){
            System.out.println("afterThrowing logging run...");
        }
        
        @After("logPointcut()")
        public void afterLogging(){
            System.out.println("after logging run...");
        }
        
        @Around("logPointcut()")
        public Object aroundLogging(ProceedingJoinPoint pjp) {
            try {
                System.out.println("前置 ...");
                Object ret = pjp.proceed();
                System.out.println("后置 ...");
                return ret;
            } catch (Throwable throwable) {
                System.out.println("异常 ...");
                throw new RuntimeException(throwable);
            } finally {
                System.out.println("最终 ...");
            }
        }
      • 注意:
        1. 分开配置 前置通知, 后置通知, 异常通知, 最终通知 运行会有点问题, 方法的调用顺序回头有点问题
          技术图片
        2. 开发中一般使用环绕通知
          技术图片

本文代码: 此处 的 spring03-aop

spring03-aop

标签:扫描   表示   inf   base   system   切面   oid   问题   编译   

原文地址:https://www.cnblogs.com/ann-zhgy/p/11783644.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!