spring后置通知、异常通知、最终通知、环绕通知

2】后置通知

切面类Security

/**切面*/

public class Security {

 

/**通知*/

/**

 * 任何通知方法可以将第一个参数定义为org.aspectj.lang.JoinPoint类型 (

 * 环绕通知需要定义第一个参数为ProceedingJoinPoint类型, 它是 JoinPoint 的一个子类)。

 * JoinPoint 接口提供了一系列有用的方法,

 * 比如 getArgs()(返回方法参数)、 

 * getThis()(返回代理对象)、

 * getTarget()(返回目标)、

 * getSignature()(返回正在被通知的方法相关信息)、

 *  toString() (打印出正在被通知的方法的有用信息)。

 */

public void checkSecurity(JoinPoint joinPoint,Object returnValue){

System.out.println("正在执行验证...");

Object [] args = joinPoint.getArgs();

if(args!=null && args.length>0){

for(Object o:args){

System.out.println("参数:"+o);

}

}

System.out.println("代理对象:"+joinPoint.getThis().getClass());

System.out.println("目标对象:"+joinPoint.getTarget().getClass());

System.out.println("访问目标对象方法的名称:"+joinPoint.getSignature().getName());

System.out.println("spring容器中定义切入点的表达式:"+joinPoint.toString());

System.out.println("目标对象方法的返回值:"+returnValue);

}

}

 

Spring容器(beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:aop="http://www.springframework.org/schema/aop"

       xsi:schemaLocation="http://www.springframework.org/schema/beans

               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

               http://www.springframework.org/schema/context

               http://www.springframework.org/schema/context/spring-context-3.0.xsd

               http://www.springframework.org/schema/aop

               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <!-- 创建目标对象 -->

    <bean id="userServiceImpl" class="cn.itcast.e_xml.b_afterReturning.UserServiceImpl"></bean>

    <!-- 声明切面 (无灵魂)-->

    <bean id="security" class="cn.itcast.e_xml.b_afterReturning.Security"></bean>

    

    

    <aop:config>

     <aop:aspect id="aa" ref="security">

     <aop:pointcut id="save" expression="execution(* cn.itcast.e_xml.b_afterReturning.UserServiceImpl.saveUser(..))" />

     <aop:pointcut id="find" expression="execution(* cn.itcast.e_xml.b_afterReturning.UserServiceImpl.findUser(..))" />

     <!-- 

     后置通知:在访问目标对象方法之后,再执行通知定义的方法

     特点:1:如果在目标对象中抛出异常,此时不会执行通知

       2:因为是先执行目标对象中的方法,再执行通知,所以能不能在通知中获取目标对象的方法的返回值?能

        第一步:在spring容器中定义:returning="returnValue"

        第二步:在通知的方法中的第二个参数,可以指定Object类型,

        例如public void checkSecurity(JoinPoint joinPoint,Object returnValue){

        总结: 参数一定要放在到第二个参数的位置

               参数一定一个Object类型

               参数的属性名称一定要与spring容器中定义的returning相一致

      -->

     <aop:after-returning pointcut-ref="save" method="checkSecurity" returning="returnValue"/>

     <aop:after-returning pointcut-ref="find" method="checkSecurity" returning="returnValue"/>

     </aop:aspect>

    </aop:config>

</beans>

 

3】异常通知

切面类Security

/**切面*/

public class Security {

 

/**通知*/

/**

 * 任何通知方法可以将第一个参数定义为org.aspectj.lang.JoinPoint类型 (

 * 环绕通知需要定义第一个参数为ProceedingJoinPoint类型, 它是 JoinPoint 的一个子类)。

 * JoinPoint 接口提供了一系列有用的方法,

 * 比如 getArgs()(返回方法参数)、 

 * getThis()(返回代理对象)、

 * getTarget()(返回目标)、

 * getSignature()(返回正在被通知的方法相关信息)、

 *  toString() (打印出正在被通知的方法的有用信息)。

 */

public void checkSecurity(JoinPoint joinPoint,Throwable throwingValue){

System.out.println("正在执行验证...");

Object [] args = joinPoint.getArgs();

if(args!=null && args.length>0){

for(Object o:args){

System.out.println("参数:"+o);

}

}

System.out.println("代理对象:"+joinPoint.getThis().getClass());

System.out.println("目标对象:"+joinPoint.getTarget().getClass());

System.out.println("访问目标对象方法的名称:"+joinPoint.getSignature().getName());

System.out.println("spring容器中定义切入点的表达式:"+joinPoint.toString());

System.out.println("目标对象方法抛出的异常是:"+throwingValue);

}

}

 

Spring容器(beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:aop="http://www.springframework.org/schema/aop"

       xsi:schemaLocation="http://www.springframework.org/schema/beans

               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

               http://www.springframework.org/schema/context

               http://www.springframework.org/schema/context/spring-context-3.0.xsd

               http://www.springframework.org/schema/aop

               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <!-- 创建目标对象 -->

    <bean id="userServiceImpl" class="cn.itcast.e_xml.c_afterThrowing.UserServiceImpl"></bean>

    <!-- 声明切面 (无灵魂)-->

    <bean id="security" class="cn.itcast.e_xml.c_afterThrowing.Security"></bean>

    

    

    <aop:config>

     <aop:aspect id="aa" ref="security">

     <aop:pointcut id="save" expression="execution(* cn.itcast.e_xml.c_afterThrowing.UserServiceImpl.saveUser(..))" />

     <aop:pointcut id="find" expression="execution(* cn.itcast.e_xml.c_afterThrowing.UserServiceImpl.findUser(..))" />

     <!-- 

     异常通知:在访问目标对象方法之后,前提是目标对象方法中抛出异常,此时才会执行通知定义的方法

     特点:1:只有目标对象方法中抛出异常,此时才会执行通知

       2:在通知的方法中捕获异常

        第一步:在spring容器中定义

        第二步:在通知的方法中的第二个参数的位置,可以指定,例如public void checkSecurity(JoinPoint joinPoint,Throwable throwingValue){

        要求一:获取目标对象抛出的异常的参数要放置在第二个参数的位置

        要求二:类型必须指定Throwable类型

        要求三:Throwable对应的属性值要和spring容器中定义的throwing="throwingValue"值要相匹配

      -->

     <aop:after-throwing pointcut-ref="save" method="checkSecurity" throwing="throwingValue"/>

     <aop:after-throwing pointcut-ref="find" method="checkSecurity" throwing="throwingValue"/>

     </aop:aspect>

    </aop:config>

</beans>

 

4】最终通知

切面类Security

/**切面*/

public class Security {

 

/**通知*/

/**

 * 任何通知方法可以将第一个参数定义为org.aspectj.lang.JoinPoint类型 (

 * 环绕通知需要定义第一个参数为ProceedingJoinPoint类型, 它是 JoinPoint 的一个子类)。

 * JoinPoint 接口提供了一系列有用的方法,

 * 比如 getArgs()(返回方法参数)、 

 * getThis()(返回代理对象)、

 * getTarget()(返回目标)、

 * getSignature()(返回正在被通知的方法相关信息)、

 *  toString() (打印出正在被通知的方法的有用信息)。

 */

public void checkSecurity(JoinPoint joinPoint){

System.out.println("正在执行验证...");

Object [] args = joinPoint.getArgs();

if(args!=null && args.length>0){

for(Object o:args){

System.out.println("参数:"+o);

}

}

System.out.println("代理对象:"+joinPoint.getThis().getClass());

System.out.println("目标对象:"+joinPoint.getTarget().getClass());

System.out.println("访问目标对象方法的名称:"+joinPoint.getSignature().getName());

System.out.println("spring容器中定义切入点的表达式:"+joinPoint.toString());

}

}

 

Spring容器(beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:aop="http://www.springframework.org/schema/aop"

       xsi:schemaLocation="http://www.springframework.org/schema/beans

               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

               http://www.springframework.org/schema/context

               http://www.springframework.org/schema/context/spring-context-3.0.xsd

               http://www.springframework.org/schema/aop

               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <!-- 创建目标对象 -->

    <bean id="userServiceImpl" class="cn.itcast.e_xml.d_after.UserServiceImpl"></bean>

    <!-- 声明切面 (无灵魂)-->

    <bean id="security" class="cn.itcast.e_xml.d_after.Security"></bean>

    

    

    <aop:config>

     <aop:aspect id="aa" ref="security">

     <aop:pointcut id="save" expression="execution(* cn.itcast.e_xml.d_after.UserServiceImpl.saveUser(..))" />

     <aop:pointcut id="find" expression="execution(* cn.itcast.e_xml.d_after.UserServiceImpl.findUser(..))" />

     <!-- 

     最终通知:在访问目标对象方法之后,不管是否抛出异常,此时都会执行通知定义的方法

     特点:1:不管目标对象是否抛出异常,都会执行通知的方法

       

      -->

     <aop:after pointcut-ref="save" method="checkSecurity"/>

     <aop:after pointcut-ref="find" method="checkSecurity"/>

     </aop:aspect>

    </aop:config>

</beans>

5】环绕通知

切面类Security

/**切面*/

public class Security {

 

/**通知*/

/**

 * 普通通知类型:

 * 任何通知方法可以将第一个参数定义为org.aspectj.lang.JoinPoint类型 (

 * 环绕通知需要定义第一个参数为ProceedingJoinPoint类型, 它是 JoinPoint 的一个子类)。

 * JoinPoint 接口提供了一系列有用的方法,

 * 比如 getArgs()(返回方法参数)、 

 * getThis()(返回代理对象)、

 * getTarget()(返回目标)、

 * getSignature()(返回正在被通知的方法相关信息)、

 *  toString() (打印出正在被通知的方法的有用信息)。

 *  

 *  环绕通知类型

 *  通知的第一个参数必须是 ProceedingJoinPoint类型。

 *  在通知体内,调用 ProceedingJoinPointproceed()方法会导致 后台的连接点方法执行。

 *  proceed 方法也可能会被调用并且传入一个 Object[]对象-该数组中的值将被作为方法执行时的参数。

 *  

 *  环绕通知将通知的方法的返回值要定义成Object类型,只有这样才能将目标对象方法的返回值,传递给客户端

 */

public Object checkSecurity(ProceedingJoinPoint joinPoint){

//如果调用joinPoint.proceed();方法放置在通知的最前面,此时就相当于后置通知

Object value = null;

try {

value = joinPoint.proceed();

catch (Throwable e) {

e.printStackTrace();

}

System.out.println("正在执行验证...");

Object [] args = joinPoint.getArgs();

if(args!=null && args.length>0){

for(Object o:args){

System.out.println("参数:"+o);

}

}

System.out.println("代理对象:"+joinPoint.getThis().getClass());

System.out.println("目标对象:"+joinPoint.getTarget().getClass());

System.out.println("访问目标对象方法的名称:"+joinPoint.getSignature().getName());

System.out.println("spring容器中定义切入点的表达式:"+joinPoint.toString());

// //如果调用joinPoint.proceed();方法放置在通知的最后,此时就相当于前置通知

// Object value = null;

// try {

// value = joinPoint.proceed();

// } catch (Throwable e) {

// e.printStackTrace();

// }

return value;

}

}

 

Spring容器(beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:aop="http://www.springframework.org/schema/aop"

       xsi:schemaLocation="http://www.springframework.org/schema/beans

               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

               http://www.springframework.org/schema/context

               http://www.springframework.org/schema/context/spring-context-3.0.xsd

               http://www.springframework.org/schema/aop

               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <!-- 创建目标对象 -->

    <bean id="userServiceImpl" class="cn.itcast.e_xml.e_around.UserServiceImpl"></bean>

    <!-- 声明切面 (无灵魂)-->

    <bean id="security" class="cn.itcast.e_xml.e_around.Security"></bean>

    

    

    <aop:config>

     <aop:aspect id="aa" ref="security">

     <aop:pointcut id="save" expression="execution(* cn.itcast.e_xml.e_around.UserServiceImpl.saveUser(..))" />

     <aop:pointcut id="find" expression="execution(* cn.itcast.e_xml.e_around.UserServiceImpl.findUser(..))" />

     <!-- 

     环绕通知:

     最后一种通知是环绕通知。环绕通知在一个目标对象方法执行之前和之后执行。

     它使得通知有机会 在一个方法执行之前和执行之后运行。而且它可以决定这个方法在什么时候执行,如何执行,甚至是否执行。

      环绕通知经常在某线程安全的环境下,你需要在一个方法执行之前和之后共享某种状态的时候使用。 

      请尽量使用最简单的满足你需求的通知。(比如如果简单的前置通知也可以适用的情况下不要使用环绕通知)。 

      -->

     <aop:around pointcut-ref="save" method="checkSecurity"/>

     <aop:around pointcut-ref="find" method="checkSecurity"/>

     </aop:aspect>

    </aop:config>

</beans>

你可能感兴趣的:(spring)