Spring aop 前置、后置、环绕通知详解

版权声明:sj专属 https://blog.csdn.net/qq_40933428/article/details/85692851

代理模式实现前置通知、后置通知和环绕通知。

代理目标接口:

package com.print;

public interface IPrinter {

   public String print(String content);

}

代理目标类:

package com.print.impl;

import com.print.IPrinter;

public class Printer implements IPrinter {

   public String print(String content) {

      System.out.println(输出内容:["+content+"]");

      return content;

   }

}

  • 前置通知:

切面类:

package com.print.advices;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MyBeforAdvice implements MethodBeforeAdvice {

   /**

    * @param m 被通知的方法对象,args 被通知的方法的参数,taget 被代理的没标类对象

    */

   public void before(Method m, Object[] args, Object taget)

        throws Throwable {

      System.out.println("前置通知开始:--------------");

      System.out.println("方法名:"+m.getName());

      System.out.println("参数列表长度:"+args.length);

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

      for(Object a : args){

        System.out.println("\t"+a.toString());

      }

      System.out.println("对象名:"+taget.getClass().getName());

      System.out.println("前置通知结束-----------------");

   }

}

Spring配置:

<!--前置通知切面bean -->

   <bean id="beforAdvice" class="com.etp.zsh.MyBeforeAdvice"/>

   <!-- 代理目标bean -->

   <bean id="taget" class="com.print.impl.Printer"/>

   <!-- 代理bean -->

   <bean id="printer" class="org.springframework.aop.framework.ProxyFactoryBean">

      <!-- 注入属性代理目标接口 -->

      <property name="proxyInterfaces" value="com.print.IPrinter "/>

      <!-- 注入属性代理目标bean -->

      <property name="target" ref="taget"/>

      <!-- 注入属性切面bean -->

      <property name="interceptorNames">

        <list>

           <value>beforAdvice</value>

        </list>

      </property>

   </bean>

测试类:

package com.print.test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.print.IPrinter;

public class Test {

   public static void main(String[] args) {

      ApplicationContext context = new FileSystemXmlApplicationContext("/src/applicationContext.xml");

      IPrinter colorPrinter = (IPrinter)context.getBean("printer");

      colorPrinter.print("do something");

   }

}

输出结果:

前置通知开始:--------------

方法名:print

参数列表长度:1

参数:

   do something

对象名:com.print.impl.Printer

前置通知结束----------------

输出内容:[do something]

 

  • 后置通知:

依然使用上边的目标类

后置通知切面类:

package com.print.advices;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MyAfterReturnAdvice implements AfterReturningAdvice {

       /**

        * @param returnObj 被通知方法的返回值, m 被通知的方法对象,args 被通知的方法的参数,taget 被代理的没标类对象

        */

       public void afterReturning(Object returnObj, Method m, Object[] args,

                     Object taget) throws Throwable {

              System.out.println("后置通知开始:--------------");

              System.out.println("方法返回值:"+ returnObj);

              System.out.println("方法名:"+m.getName());

              System.out.println("参数列表长度:"+args.length);

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

              for(Object a : args){

                     System.out.println("\t"+a.toString());

              }

              System.out.println("对象名:"+taget.getClass().getName());

              System.out.println("后置通知结束----------------");

       }

}

applicationContext.xml中添加后置通知切面bean配置:

<!-- 后置通知切面 -->

   <bean id="arterReturnAdvice" class="com.print.advices.MyAfterReturnAdvice"/>

在代理bean中添加切面arterReturnAdvice:

<property name="interceptorNames">

        <list>

           <value>beforAdvice</value>

           <value>arterReturnAdvice</value>

        </list>

      </property>

运行测试,得到结果:

前置通知开始:--------------

方法名:print

参数列表长度:1

参数:

   do something

对象名:com.print.impl.Printer

前置通知结束----------------

输出内容:[do something]

后置通知开始:--------------

方法返回值:do something

方法名:print

参数列表长度:1

参数:

   do something

对象名:com.print.impl.Printer

后置通知结束----------------

 

三、环绕通知:

依然使用上边的目标类

环绕通知切面类:

package com.print.advices;

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

public class MyInterceptor implements MethodInterceptor {

       /**

        * @param invocation 被代理的目标对象

        */

       public Object invoke(MethodInvocation invocation) throws Throwable {

              Object returnObj = null;

              System.out.println("{{{{{{环绕通知开始}}}}}}");

              //执行代理目标的被通知的方法

              returnObj = invocation.proceed();

              System.out.println("{{{{{{环绕通知结束}}}}}}");

              return returnObj;

       }

}

applicationContext.xml中添加环绕通知切面bean配置:

<!-- 环绕通知切面 -->

   <bean id="myInterceptor" class="com.print.advices.MyInterceptor"/>

在代理bean中添加切面myInterceptor:

<property name="interceptorNames">

        <list>

           <value>beforAdvice</value>

           <value>arterReturnAdvice</value>

<value>myInterceptor</value>

        </list>

      </property>

运行测试,得到结果:

前置通知开始:--------------

方法名:print

参数列表长度:1

参数:

   do something

对象名:com.print.impl.Printer

前置通知结束----------------

{{{{{{环绕通知开始}}}}}}

输出内容:[do something]

{{{{{{环绕通知结束}}}}}}

后置通知开始:--------------

方法返回值:do something

方法名:print

参数列表长度:1

参数:

   do something

对象名:com.print.impl.Printer

后置通知结束----------------

 

猜你喜欢

转载自blog.csdn.net/qq_40933428/article/details/85692851
今日推荐