深入浅出Spring(三) 五种通知

通知简介

  • 前置通知(Before advice)

    在目标方式执行之前执行,所以获取不到目标方法执行后的返回值
    
  • 后置通知(After returning advice)

    1. 后置通知可以获取到目标方法的返回值
    2. 当目标方法抛出异常,后置通知将不再执行
  • 异常通知(After throwing advice)

    目标方法发生 异常时执行
    
  • 最终通知(finally advice)

    无论目标方法是否抛出异常都将执行
    
  • 环绕通知(Around advice)

     通过joinPoint.proceed()控制目标方法的执行
    

实例

目标类:PersonDaoImpl.java

public class PersonDaoImpl implements PersonDao{
    public String savePerson() {
//      int a = 1/0;
        System.out.println("save person");
        return "aaa";
    }
}               

切面:Transaction.java

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

//切面
public class Transaction {
    /*
     * 前置通知
     *     在目标方法执行之前
     * joinPoint :连接点
     */
    public void beginTransaction(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("连接点的名称:"+methodName);
        System.out.println("目标类:"+joinPoint.getTarget().getClass());
        System.out.println("begin transaction");
    }

    /**
     * 后置通知
     *     在目标方法执行之后
     */
    public void commit(JoinPoint joinPoint,Object val){
        System.out.println("目标方法的返回值:"+val);
        System.out.println("commit");
    }

    /**
     * 最终通知
     */
    public void finallyMethod(){
        System.out.println("finally method");
    }

    /**
     * 异常通知
     *    接受目标方法抛出的异常
     */
    public void throwingMethod(JoinPoint joinPoint,Throwable ex){
        System.out.println(ex.getMessage());
    }

    /**
     * 环绕通知
     *   joinPoint.proceed();这个代码如果在环绕通知中不写,则目标方法不再执行
     */
    public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕通知");
        joinPoint.proceed();//调用目标方法
    }
}

配置文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <bean id="personDao" class="com.kelly.spring.aop.xml.transaction.PersonDaoImpl"></bean>
    <bean id="transaction" class="com.kelly.spring.aop.xml.transaction.Transaction"></bean>

    <aop:config>
        <!-- 
            切入点表达式  确定目标类
         -->
        <aop:pointcut 
            expression="execution(* com.kelly.spring.aop.xml.transaction.PersonDaoImpl.*(..))" 
            id="perform"/>
        <!-- 
            ref指向的对象就是切面
         -->
        <aop:aspect ref="transaction">
            <!-- 
                前置通知
                   1、在目标方法执行之前
                   2、获取不到目标方法的返回值
             -->

            <aop:before method="beginTransaction" pointcut-ref="perform"/>

            <!-- 
                后置通知
                   1、后置通知可以获取到目标方法的返回值
                   2、当目标方法抛出异常,后置通知将不再执行
             -->
             <!-- 
            <aop:after-returning method="commit" pointcut-ref="perform" returning="val"/>
             -->
            <!-- 
                最终通知
                   无论目标方法是否抛出异常都将执行
             -->
            <aop:after method="finallyMethod" pointcut-ref="perform"/>
            <!-- 
                异常通知
             -->
            <aop:after-throwing method="throwingMethod" throwing="ex" pointcut-ref="perform"/>
            <!-- 
                环绕通知
                        能控制目标方法的执行
                        前置通知和后置通知能在目标方法的前面和后面加一些代码,但是不能控制目标方法的执行
             -->
            <aop:around method="aroundMethod" pointcut-ref="perform"/>
        </aop:aspect>
    </aop:config>
</beans>

客户端调用 : TransactionTest.java

public class TransactionTest {
    @Test
    public void testTransaction(){
        ApplicationContext context = 
                new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonDao personDao = (PersonDao)context.getBean("personDao");
        personDao.savePerson();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值