Spring学习心得(18)-- 通知的种类

来源:互联网 发布:unity3d ios 交互 编辑:程序博客网 时间:2024/05/21 17:32

通知的种类:

1、前置通知2、后置通知3、最终通知4、异常通知5、环绕通知

在之前的例子中,我们使用到了before(前置通知)和after-returning(后置通知)。还有after最终通知(最终通知)和around(环绕通知)。


前置通知和后置通知已经在前面的帖子涉及到,这里只做总结:

前置通知:

*在目标方法执行前执行*所以目标方法如果出现异常,这里还会执行

后置通知:

*在目标方法执行后执行*如果目标方法出现异常,这里不会执行*可以接收由目标方法的返回值

配置如下: 

*注意:这些配置是在标签里面定义的

 <!--         aop配置      -->      <aop:config>        <!--             aop:pointcut 指的是切入点判断,我们昨天使用的是在拦截器中使用if方法,具体内容可以看上一篇帖子                         但是考虑到如果有很多个dao,那么就要判断很多次,效率会降低            expression   指的是切入点的表达式,该表达式的作用就是调用哪些方法,                         一般都使用简写形式,即只需标明 (* *(..)),                         第一个*是指返回值类型,第二个是指方法全名                         括号中的.. 类似于可变参数的作用,                          在这里我们执行的是目标类PersonDaoImpl 的某个方法            id          是指对这个切入点的唯一标识符         -->        <aop:pointcut expression="execution(* cn.ansel.aopExample.PersonDaoImpl.*(..))" id="perform"/>        <!--             aop:aspect  定义切面,因为要把相应的类定义到配置文件中才算是切面            id          该切面的唯一标识符               ref         该切面的引用对象         -->        <aop:aspect id="mytransaction" ref="myTransaction">             <!--                 method          指对应切面中的通知,这里的method对应的切面,就是上级标签ref对应的切面                pointcut-ref    指该值对应的切入点表达式                before          指前置通知的配置              -->            <aop:before method="before" pointcut-ref="perform" />            <!--                 aop:after-returning   指后置通知的定义标签                returning             指目标方法中返回值的名称             -->            <aop:after-returning method="afterReturning" pointcut-ref="perform" returning="var"/>        </aop:aspect>      </aop:config>

/目标类的代码:public class PersonDaoImpl extends hibernateUtil  {    public String savePerson(Person person) {        System.out.println("targetMethod");        //返回字符串        return "the object form targetMethod";    }}//切面中方法:public class MyTransaction extends hibernateUtil{    public void before(){        System.out.println("beforeMethod");    }    public void afterReturning(Object var){        //接收目标类返回值,并输出        System.out.println(var);    }}//测试类的方法:public class testAOP {    @Test    public void test(){        //加载spring配置文件        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("cn/ansel/aopExample/applicationContext.xml");        //得到目标类        PersonDaoImpl dao=(PersonDaoImpl) applicationContext.getBean("personDaoImpl");        //存入数据        Person person=new Person();        person.setPname("ansel");        person.setPdescription("fine");        dao.savePerson(person);    }}

运行结果: 
这里写图片描述

*主要注意的是:在配置文件中配置的returning参数的名字,必须与切面的后置通知中的传入参数的名字要一致,否则会报错 
example:

 //我把后置通知中的传入参数名字改成sth,然后再输出sth    public void afterReturning(Object sth){        //接收目标类返回值,并输出        System.out.println(sth);    }

此时,目标方法不变,继续执行测试类的运行结果,有一大堆报错,于是我标注了重要的提示: 
这里写图片描述

最终通知:

直接看配置:在切面中,直接写一个新的方法作为最终通知,然后在配置文件中配置
 //最终通知    public void after(){        System.out.println("after");    }<!--    配置文件中的配置,在刚刚后置通知的后面加上这一行代码    after  指最终通知,其他没有什么不同,需要注意的是,配置每一个通知的时候,都不要忘记了pointcut-ref的引用--><aop:after method="after" pointcut-ref="perform" />

目标方法不变,运行结果: 
这里写图片描述

要看最终通知有什么真正的效果,由于最终的名字,想到了Java中有一个finally代码块,所以我们在目标方法加一个异常:

public class PersonDaoImpl extends hibernateUtil  {    public String savePerson(Person person) {        //添加一个异常,用来测试最终通知的作用        int a=1/0;        System.out.println("targetMethod");        //返回字符串        return "the object form targetMethod";    }}

运行结果:毫无意外的报了异常,可是最终通知运行了,后置通知没有运行,目标方法也没有运行 
这里写图片描述

由此可以看出,最终通知跟finally代码块的作用是一致的,finally也是最终的意思好吧。。

异常通知:

该通知的作用主要用于返回目标方法中出现的异常。配置如下:

在切面中增加这样一个方法:

 /**     * 异常通知     * @param ex 参数为目标方法中返回的异常,改名字与配置文件中的throwing配置的名字要一致     *           否则跟上面返回值一样报错     */    public void throwing(Throwable ex){        System.out.println(ex.getMessage());    }
<!--     配置文件:                aop:after-throwing 指异常通知,接收目标方法发生的异常                throwing                指目标方法抛出异常的引用名-->            <aop:after-throwing method="throwing" pointcut-ref="perform" throwing="ex"/>

测试类不变,运行结果为: 
这里写图片描述

环绕通知:

用来控制目标方法是否执行。
//ProceedingJoinPoint 该类有一个proceed方法,用来控制目标方法是否执行。 在这里我们先不用那个方法,看看目标方法是否会执行public void around(ProceedingJoinPoint joinPoint){        System.out.println("around");    }
配置文件:

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

运行结果: 
这里写图片描述 
在目标方法中有

int a=1/0l
  • 1
  • 1

但是没有报错,并且只是执行了前置通知和环绕通知。这时候最终通知也不执行了。 
但是当我调用ProceedingJoinPoint类的proceed方法时,这里先把异常代码注释掉: 
目标类代码:

public class PersonDaoImpl extends hibernateUtil  {    public String savePerson(Person person) {        //添加一个异常,用来测试最终通知的作用//      int a=1/0;        System.out.println("targetMethod");        //返回字符串        return "the object form targetMethod";    }}
环绕通知的代码该为:

public void around(ProceedingJoinPoint joinPoint) throws Throwable{        System.out.println("around");        //调用proceed方法        joinPoint.proceed();    }

运行结果为: 
这里写图片描述 
全部配置的通知都执行了,除了异常通知。










0 0
原创粉丝点击