AOP的五种通知

基于XML的SpringAOP开发

在XML中配置AOP

    <!-- AOP配置 -->
<aop:config>
    <!-- 配置切入点:告诉spring框架哪些方法需要被增强 -->
    <aop:pointcut expression="execution(* cn.itcast.dao.impl.CustomerDaoImpl.save(..))" id="pointcut1"/>
    <!-- 配置切面:告诉spring框架调用切面类中的哪个方法来增强 -->
    <aop:aspect ref="myAspectXml">
        <aop:before method="writeLog" pointcut-ref="pointcut1"/>
    </aop:aspect>
</aop:config>  

- 切入点表达式语法:[修饰符] 返回类型 包名.类名.方法名(形式参数)
- 常见写法:

    execution(public * *(..))                                   所有的public方法  
    execution(* set*(..))                                       所有set开头的方法  
    execution(* com.xyz.service.AccountService.*(..))           AccountService类中的所有方法    
    execution(* com.xyz.service.*.*(..))                        com.xyz.service包下所有的方法  
    execution(* com.xyz.service..*.*(..))   ·                   com.xyz.service包及其子包下所有的方法

AOP的通知类型

    <!-- 配置AOP--> 
<aop:config>
    <!-- 配置切入点(Pointcut):告诉框架哪些方法需要被增强 -->     
    <aop:pointcut expression="execution(* cn.itcast.dao.impl.CustomerDaoImpl.save(..))" id="pointcut1"/>
    <!-- 配置切面(Aspect):告诉框架调用切面的哪个方法来增强切点方法 以及通知类型  <aop:before /> -->  
    <aop:aspect ref="myAspectXml">
        <aop:before method="writelog" pointcut-ref="pointcut1"/>
    </aop:aspect>
</aop:config> 

前置通知

应用:权限控制(权限不足抛出异常)、记录方法调用信息日志

    <!-- 配置前置通知:告诉spring在目标方法执行之前增强 -->
  <aop:before method="before" pointcut-ref="pointcut1"/>  

切面类中的增强方法

/**
 * 前置通知方法 应用场景: 权限控制 (权限不足,抛出异常)、 记录方法调用信息日志
 * joinPoint:连接点,指的是被增强的那个方法
 */
public void before(JoinPoint joinPoint) {
    String username = "rose";
    if (!"admin".equals(username)) {
        // 非admin用户,不具备权限,抛出异常
        //joinPoint.getTarget().getClass().getName()获取目标类的名字
        //joinPoint.getSignature().getName()获取被增强方法的名字
        throw new RuntimeException("对不起!您没有对" + joinPoint.getTarget().getClass().getName() + "类中"
                + joinPoint.getSignature().getName() + "方法的访问权限");
    }
}

后置通知

特点:在目标方法运行后返回值后再增强代码逻辑
应用:于业务相关的, 如银行在存取款结束后的发送短信消息

    <!-- 配置后置通知 -->  
    <!-- returning="result" 目标方法返回值为result-->  
   <aop:after-returning method="afterReturning" pointcut-ref="pointcut2" returning="result"/> 

方法

/**
 * 后置通知方法
 * 应用场景: ATM取款机取款后,自动下发短信
 * 参数result:被增强那个方法的返回值
 */
public void afterReturning(JoinPoint joinPoint,Object result){
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String dateStr = sdf.format(date);
    System.out.println("尊敬的用户,您于" + dateStr + "取款" + result + "元");
    }
}

环绕通知

特点 :目标方法执行前后,都进行增强(控制目标方法执行)
应用 :日志、缓存、权限、性能监控、事务管理

增强代码的方法要求:
- 接收的参数:ProceedingJoinPoint(可执行的连接点)
- 返回值: Object返回值
- 抛出Throwable异常

<!-- 配置环绕通知 -->
    <aop:around method="around" pointcut-ref="pointcut3"/>    


/**
 * 环绕通知方法
 * 应用场景:事务处理
 * @param proceedingJoinPoint 正在执行的连接点
 */
public Object around(ProceedingJoinPoint proceedingJoinPoint){
    System.out.println("开启事务");
    //获取目标方法的参数
    Object[] args = proceedingJoinPoint.getArgs();
    Object result = null;
    try {
        //调用目标方法,获取目标方法的返回值
        result = proceedingJoinPoint.proceed(args);
        System.out.println("提交事务");
    } catch (Throwable e) {
        System.out.println("回滚事务");
    }
    //返回目标方法的返回值
    return result;
    }
}

异常抛出通知

作用:目标代码出现异常,通知执行。记录异常日志、通知管理员(短信、邮件)
应用场景:处理异常(一般不可预知),记录日志

<!-- 异常抛出通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
/**
 * @param joinPoint
 * @param ex 目标方法抛出的异常 要与配置文件命名一致
 */
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
    System.out.println("注意了:在" + joinPoint.getTarget().getClass().getName() + "中的"
            + joinPoint.getSignature().getName() + "方法中发生了异常:" + ex.getMessage());
}

最终通知

作用:不管目标方法是否发生异常,最终通知都会执行(类似于finally代码功能)
应用场景:释放资源 (关闭文件、 关闭数据库连接、 网络连接、 释放内存对象 )

<!-- 最终通知 -->
    <aop:after method="after" pointcut-ref="pointcut4" />
public void after(JoinPoint joinPoint){
    System.out.println("开始释放资源,对应的连接点信息为:" + joinPoint.getTarget().getClass().getName() + "的"
            + joinPoint.getSignature().getName() + "方法");
}

注意,最终通知和后置通知的区别:最终通知,不管异常与否,都执行;而后置通知在异常时不执行。

猜你喜欢

转载自blog.csdn.net/luoxiao2554/article/details/80427817