5.8 把输出日志的实例改成用Spring的AOP来实现

来源:互联网 发布:短网址生成算法 编辑:程序博客网 时间:2024/05/22 08:00

 

5.8  把输出日志的实例改成用Spring的AOP来实现

在前面输出日志信息的实例中,没有用到Spring的任何组件,只是使用了Java的动态代理机制,但是却实实在在地体现了AOP的思想,如果使用Spring提供的AOP功能,应该怎样来实现前面那个实例呢?下面笔者就主要讲解如何把前面的那个实例改成通过Spring提供的AOP来实现。

5.8.1  采用Interception Around通知的形式实现

Interception Around通知会在JointPoint的前后执行,实现Interception Around通知的类需要实现接口MethodInterceptor。其实现思路是:首先实现接口MethodInterceptor,在invoke()方法里编写负责输出日志信息的代码,具体的业务逻辑还使用前面的接口TimeBookInterface和它的实现类TimeBook,然后在Spring的配置文档中定义Pointcut,最后编写测试程序,执行测试程序,查看输出结果。具体步骤如下:

(1)编写负责输出日志信息的类LogAround,该类实现了接口MethodInterceptor,重写了invoke()方法。LogAround.java的示例代码如下:

//******* LogAround.java**************

package com.gc.action;

import org.aopalliance.intercept.MethodInvocation;

import org.aopalliance.intercept.MethodInterceptor;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

// Interception Around通知会在JointPoint的前后执行

public class LogAround implements MethodInterceptor {

         private Logger logger = Logger.getLogger(this.getClass().getName());

     //负责输出日志信息的代码

     public Object invoke(MethodInvocation mi) throws Throwable {

                   logger.log(Level.INFO, mi.getArguments()[0] + " 开始审核数据...."); 

        try {

          Object result = mi.proceed();

                    //返回值即是被调用的方法的返回值

          return result;

        }

        finally {

                            logger.log(Level.INFO, mi.getArguments()[0] + " 审核数据结束....");

        }       

   }

}

代码说明:

  ●       参数MethodInvocation,通过它可以获得方法的名称、程序传入的参数Object[]等。

  ●       proceed()方法,通过它即可执行被调用的方法。

  ●       return result,返回值即是被调用的方法的返回值。

(2)使用com.gc.impl包中的接口TimeBookInterface。TimeBookInterface.java的示例代码如下:

//******* TimeBookInterface.java**************

package com.gc.impl;

import org.apache.log4j.Level;

public interface TimeBookInterface {

         //负责具体的业务逻辑

         public void doAuditing(String name);

}

(3)使用com.gc.action包中的类TimeBook,doAuditing()方法中编写具体的考勤审核代码。TimeBook.java的示例代码如下:

//******* TimeBook.java**************

package com.gc.action;

import com.gc.impl.TimeBookInterface;

public class TimeBook implements TimeBookInterface {

public void doAuditing(String name) {

//审核数据的相关程序

……   

}

}

(4)定义Spring的配置文档config.xml。config.xml的示例代码如下:

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

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!--使用依赖注入完成变量值设定-->

  <bean id="HelloWorld" class="com.gc.action.HelloWorld" depends-on="date">

      <property name="msg">

          <value>HelloWorld</value>

      </property>

<!--使用Bean进行参考-->

<property name="date">

<ref bean="date"/>

</property>

</bean>

<bean id="date" class="java.util.Date"/>

<!--以下是使用Spring AOP实现日志输出的Bean-->

<bean id="log" class="com.gc.action.LogAround"/>

<bean id="timeBook" class="com.gc.action.TimeBook"/>

<!--使用Spring提供的ProxyFactoryBean来实现代理-->

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

               <!--指定要代理的类-->

        <property name="interceptorNames">

            <list>

                <value>log</value>

            </list>

        </property>

    </bean>

</beans>

代码说明:

  ●       id为log的Bean,负责输出日志信息。

  ●       id为timeBook的Bean,负责具体的业务逻辑考勤审核。

  ●       id为logProxy的Bean,使用Spring提供的ProxyFactoryBean来实现代理,在该Bean里要定义相关的属性,包括要代理的接口、目标类以及要使用的Interceptor。

(5)修改测试代码TestHelloWorld,使用Spring提供的代理类ProxyFactoryBean实现日志的输出。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

             //通过ApplicationContext获取XML

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml"); 

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy");

timeBookProxy.doAuditing("张三");

    }

}

(6)运行测试程序,可以得到通过LogAround类输出日志信息,如图5.4所示。

图5.4  通过LogAround类输出日志信息

上面这个例子即实现了Interception Around通知,最终的效果和前面使用Java代理的效果一样,但是功能却更加强大。假如有一个新的关账程序要实现日志输出,则可以建立新的接口和其实现类,然后只要在配置文件中注册一下就可以使新的实现类也输出日志信息了。

(7)在com.gc.impl包中建立新的接口FinanceInterface。FinanceInterface.java的示例代码如下:

//******* FinanceInterface.java**************

package com.gc.impl;

import org.apache.log4j.Level;

//定义为接口主要是为了实现代理

public interface FinanceInterface {

         public void doCheck(String name);

}

(8)在com.gc.action包中新建类Finance,doCheck()方法中编写具体的财务关账代码。Finance.java的示例代码如下:

//******* Finance.java**************

package com.gc.action;

import com.gc.impl. FinanceInterface;

public class Financeimplements FinanceInterface {

public void doCheck (String name) {

//关账的相关程序

……   

}

}

(9)定义Spring的配置文档config.xml。config.xml的示例代码如下:

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

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

  <!--使用依赖注入完成变量值设定-->

  <bean id="HelloWorld" class="com.gc.action.HelloWorld" depends-on="date">

      <property name="msg">

          <value>HelloWorld</value>

      </property>

<property name="date">

<ref bean="date"/>

</property>

</bean>

<bean id="date" class="java.util.Date"/>

<!--以下是使用Spring AOP实现日志输出的Bean-->

<bean id="log" class="com.gc.action.LogAround"/>

<bean id="timeBook" class="com.gc.action.TimeBook"/>

<!--以下是考勤审核-->

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

               <!--指定要代理的类-->

        <property name="interceptorNames">

            <list>

                <value>log</value>

            </list>

        </property>

    </bean>

<!--以下是财务关账-->

<bean id="finance" class="com.gc.action.Finance"/>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.FinanceInterface</value>

        </property>

        <property name="target">

            <ref bean="finance"/>

        </property>

<!--指定要代理的类-->

        <property name="interceptorNames">

            <list>

                <value>log</value>

            </list>

        </property>

    </bean>

</beans>

代码说明:

  ●       id为finance的Bean,负责具体的业务逻辑财务关账。

  ●       id为logProxy1的Bean,使用Spring提供的ProxyFactoryBean来实现代理,在该Bean里要定义相关的属性,包括要代理的接口、目标类以及要使用的Interceptor。

(10)修改测试代码TestHelloWorld,使用Spring提供的代理类ProxyFactoryBean实现日志的输出。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

import com.gc.impl.FinanceInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

//通过ApplicationContext获取XML

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");     

FinanceInterface financeProxy = (FinanceInterface)actx.getBean("logProxy1");

financeProxy.doCheck("李四");

    }

}

(11)运行测试程序,可以得到通过LogAround类输出日志信息,如图5.5所示。

图5.5  通过LogAround类输出日志信息

5.8.2  采用Before通知的形式实现

Before通知只在JointPoint的前面执行,实现Before通知的类需要实现接口MethodBeforeAdvice。实现思路是:首先实现接口MethodBeforeAdvice,在before()方法里编写负责输出日志信息的代码,具体的业务逻辑还使用前面的接口TimeBookInterface和它的实现类TimeBook,然后在Spring的配置文档中定义Pointcut,最后测试程序不用改变,执行测试程序,查看输出结果。具体步骤如下:

(1)编写负责输出日志信息的类LogBefore,该类实现了接口MethodBeforeAdvice,重写了before()方法。LogBefore.java的示例代码如下:

//******* LogBefore.java**************

package com.gc.action;

import java.lang.reflect.Method;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.springframework.aop.MethodBeforeAdvice;

//实现Before通知的类需要实现接口MethodBeforeAdvice

public class LogBefore implements MethodBeforeAdvice {

         private Logger logger = Logger.getLogger(this.getClass().getName());

    // Before通知只在JointPoint的前面执行

    public void before(Method method, Object[ ] args, Object target) throws Throwable {

                   logger.log(Level.INFO, args[0] + " 开始审核数据....");

   }

}

(2)使用com.gc.impl包中的接口TimeBookInterface。TimeBookInterface.java的示例代码如下:

//******* TimeBookInterface.java**************

package com.gc.impl;

import org.apache.log4j.Level;

public interface TimeBookInterface {

         public void doAuditing(String name);

}

(3)使用com.gc.action包中的类TimeBook,doAuditing()方法中编写具体的考勤审核代码。TimeBook.java的示例代码如下:

//******* TimeBook.java**************

package com.gc.action;

import com.gc.impl.TimeBookInterface;

public class TimeBook implements TimeBookInterface {

public void doAuditing(String name) {

//审核数据的相关程序

……   

}

}

(4)定义Spring的配置文档config.xml。config.xml的示例代码如下:

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

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

   <!--使用依赖注入完成变量值设定-->

  <bean id="HelloWorld" class="com.gc.action.HelloWorld" depends-on="date">

      <property name="msg">

          <value>HelloWorld</value>

      </property>

<property name="date">

<ref bean="date"/>

</property>

</bean>

<bean id="date" class="java.util.Date"/>

<!--以下是使用Spring AOP实现日志输出的Bean-->

<bean id="log" class="com.gc.action.LogAop"/>

<!--负责具体的业务逻辑考勤审核-->

<bean id="timeBook" class="com.gc.action.TimeBook"/>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

                <!--指定要代理的类-->

        <property name="interceptorNames">

            <list>

                <value>log</value>

            </list>

        </property>

    </bean>

<!--以下是实现Before通知-->

<bean id="logBefore" class="com.gc.action.LogBefore"/>

  <bean id="logBeforeAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logBefore"/>

        </property>

        <!--代理指定类中的doAuditing 方法-->

        <property name="patterns">

            <value>.*doAuditing.* </value>

        </property>

    </bean>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

<!--指定要代理的类-->

        <property name="interceptorNames">

            <list>

                <value>logBeforeAdvisor</value>

            </list>

        </property>

  </bean>

</beans>

代码说明:

  ●       id为timeBook的Bean,负责具体的业务逻辑考勤审核。

  ●       id为logProxy2的Bean,使用Spring提供的ProxyFactoryBean来实现代理,在该Bean里要定义相关的属性,包括要代理的接口、目标类以及要使用的Interceptor。

  ●       id为logBeforeAdvisor的Bean,使用类RegexpMethodPointcutAdvisor来实现对切入点的配置

  ●       属性名为patterns的值,指明只对doAuditing()方法有效。

(5)修改测试代码TestHelloWorld,使用Spring提供的代理类ProxyFactoryBean实现日志的输出。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

                   //通过ApplicationContext来获取XML

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");      

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy2");

timeBookProxy.doAuditing("张三");

    }

}

(6)运行测试程序,可以得到通过LogBefore类输出日志信息,如图5.6所示。

图5.6  通过LogBefore类输出日志信息

上面这个例子即实现了Before通知。

5.8.3  采用After Returning通知的形式实现

After Returning通知只在JointPoint的后面执行,实现After Returning通知的类需要实现接口AfterReturningAdvice。其实现思路是:首先实现接口AfterReturningAdvice,在afterReturning()方法里编写负责输出日志信息的代码,具体的业务逻辑还使用前面的接口TimeBookInterface和它的实现类TimeBook,然后在Spring的配置文档中定义Pointcut,最后测试程序不用改变,执行测试程序,查看输出结果。具体步骤如下:

(1)编写负责输出日志信息的类LogAfter,该类实现了接口AfterReturningAdvice,重写了afterReturning()方法。LogAfter.java的示例代码如下:

//******* LogAfter.java**************

package com.gc.action;

import java.lang.reflect.Method;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.springframework.aop.AfterReturningAdvice ;

// After Returning通知只在JointPoint的后面执行

public class LogAfter implements AfterReturningAdvice  {

         private Logger logger = Logger.getLogger(this.getClass().getName());

    //实现After Returning通知的类需要实现接口AfterReturningAdvice

    public void afterReturning(Object object, Method method, Object[ ] args, Object target) throws Throwable {

                   logger.log(Level.INFO, args[0] + " 审核数据完成...");

   }

}

(2)使用com.gc.impl包中的接口TimeBookInterface。TimeBookInterface.java的示例代码如下:

//******* TimeBookInterface.java**************

package com.gc.impl;

import org.apache.log4j.Level;

//审核数据的相关程序

public interface TimeBookInterface {

         public void doAuditing(String name);

}

(3)使用com.gc.action包中的类TimeBook,doAuditing()方法中编写具体的考勤审核代码。TimeBook.java的示例代码如下:

//******* TimeBook.java**************

package com.gc.action;

import com.gc.impl.TimeBookInterface;

public class TimeBook implements TimeBookInterface {

public void doAuditing(String name) {

//审核数据的相关程序

……   

}

}

(4)定义Spring的配置文档config.xml。config.xml的示例代码如下:

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

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

  <bean id="HelloWorld" class="com.gc.action.HelloWorld" depends-on="date">

      <property name="msg">

          <value>HelloWorld</value>

      </property>

<property name="date">

<ref bean="date"/>

</property>

</bean>

<bean id="date" class="java.util.Date"/>

<!--以下是使用Spring AOP实现日志输出的Bean-->

<bean id="log" class="com.gc.action.LogAop"/>

<bean id="timeBook" class="com.gc.action.TimeBook"/>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

                <!--指定代理类-->

        <property name="interceptorNames">

            <list>

                <value>log</value>

            </list>

        </property>

    </bean>

<!--以下是实现Before通知-->

<bean id="logBefore" class="com.gc.action.LogBefore"/>

  <bean id="logBeforeAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logBefore"/>

        </property>

                <!--只对doAuditing()方法有效-->

        <property name="patterns">

            <value>.*doAuditing.* </value>

        </property>

    </bean>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

                <!--指定代理类-->

        <property name="interceptorNames">

            <list>

                <value>logBeforeAdvisor</value>

            </list>

        </property>

  </bean>

<!--以下是实现After通知-->

<bean id="logAfter" class="com.gc.action.LogAfter"/>

  <bean id="logAfterAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logAfter"/>

        </property>

                <!--只对doAuditing()方法有效-->

        <property name="patterns">

            <value>.*doAuditing.* </value>

        </property>

    </bean>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

                <!--指定代理类-->

        <property name="interceptorNames">

            <list>

                <value>logAfterAdvisor</value>

            </list>

        </property>

  </bean>

</beans>

代码说明:

  ●       id为timeBook的Bean,负责具体的业务逻辑考勤审核。

  ●       id为logProxy3的Bean,使用Spring提供的ProxyFactoryBean来实现代理,在该Bean里要定义相关的属性,包括要代理的接口、目标类以及要使用的Interceptor。

  ●       id为logAfterAdvisor的Bean,使用类RegexpMethodPointcutAdvisor来实现对切入点的配置。

  ●       属性名为patterns的值,指明只对doAuditing()方法有效。

(5)修改测试代码TestHelloWorld,使用Spring提供的代理类ProxyFactoryBean 实现日志的输出。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

            //通过ApplicationContext获取配置文档

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml"); 

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy3");

timeBookProxy.doAuditing("张三");

    }

}

(6)运行测试程序,可以得到通过LogAfter类输出日志信息,如图5.7所示。

图5.7  通过LogAfter类输出日志信息

5.8.4  采用Throw通知的形式实现

Throw通知只在JointPoint抛出异常时执行,实现Throw通知的类需要实现接口ThrowsAdvice。实现思路是:首先实现接口ThrowsAdvice,在afterThrowing()方法里编写负责输出日志信息的代码,具体的业务逻辑还使用前面的接口TimeBookInterface和它的实现类TimeBook,然后在Spring的配置文档中定义Pointcut,最后测试程序不用改变,执行测试程序,查看输出结果。具体步骤如下:

(1)编写负责输出日志信息的类LogThow,该类实现了接口ThrowsAdvice,重写了afterThrowing()方法。LogThow.java的示例代码如下:

//******* LogThow.java**************

package com.gc.action;

import java.lang.reflect.Method;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.springframework.aop.ThrowsAdvice ;

//实现Throw通知的类需要实现接口ThrowsAdvice

public class LogThrow implements ThrowsAdvice  {

         private Logger logger = Logger.getLogger(this.getClass().getName());

    //在afterThrowing()方法里编写负责输出日志信息的代码

    public void afterThrowing(Method method, Object[ ] args, Object target, Throwable subclass) throws Throwable {

                   logger.log(Level.INFO, args[0] + " 审核数据有异常抛出...");

   }

}

(2)使用com.gc.impl包中的接口TimeBookInterface。TimeBookInterface.java的示例代码如下:

//******* TimeBookInterface.java**************

package com.gc.impl;

import org.apache.log4j.Level;

//针对接口编程

public interface TimeBookInterface {

         public void doAuditing(String name);

}

(3)使用com.gc.action包中的类TimeBook,doAuditing()方法中编写具体的考勤审核代码。TimeBook.java的示例代码如下:

//******* TimeBook.java**************

package com.gc.action;

import com.gc.impl.TimeBookInterface;

public class TimeBook implements TimeBookInterface {

public void doAuditing(String name) {

//审核数据的相关程序

……   

}

}

(4)定义Spring的配置文档config.xml。config.xml的示例代码如下:

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

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

  <bean id="HelloWorld" class="com.gc.action.HelloWorld" depends-on="date">

      <property name="msg">

          <value>HelloWorld</value>

      </property>

<property name="date">

<ref bean="date"/>

</property>

</bean>

<bean id="date" class="java.util.Date"/>

<!--以下是使用Spring AOP实现日志输出的Bean-->

<bean id="log" class="com.gc.action.LogAop"/>

<bean id="timeBook" class="com.gc.action.TimeBook"/>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

               <!--指定代理类-->

        <property name="interceptorNames">

            <list>

                <value>log</value>

            </list>

        </property>

    </bean>

<!--以下是实现Before通知-->

<bean id="logBefore" class="com.gc.action.LogBefore"/>

  <bean id="logBeforeAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logBefore"/>

        </property>

               <!--只对doAuditing 方法有效-->

        <property name="patterns">

            <value>.*doAuditing.* </value>

        </property>

    </bean>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

               <!--指定代理类-->

        <property name="interceptorNames">

            <list>

                <value>logBeforeAdvisor</value>

            </list>

        </property>

  </bean>

<!--以下是实现After通知-->

<bean id="logAfter" class="com.gc.action.LogAfter"/>

  <bean id="logAfterAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logAfter"/>

        </property>

               <!--只对doAuditing 方法有效-->

        <property name="patterns">

            <value>.*doAuditing.* </value>

        </property>

    </bean>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

               <!--指定代理类-->

        <property name="interceptorNames">

            <list>

                <value>logAfterAdvisor</value>

            </list>

        </property>

  </bean>

<!--以下是实现Throw通知-->

<bean id="logThrow" class="com.gc.action.LogThrow"/>

  <bean id="logThrowAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">

            <ref bean="logThrow"/>

        </property>

               <!--只对doAuditing 方法有效-->

        <property name="patterns">

            <value>.*doAuditing.* </value>

        </property>

    </bean>

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

        <property name="proxyInterfaces">

            <value>com.gc.impl.TimeBookInterface</value>

        </property>

        <property name="target">

            <ref bean="timeBook"/>

        </property>

               <!--指定代理类-->

        <property name="interceptorNames">

            <list>

                <value>logThrowAdvisor</value>

            </list>

        </property>

  </bean>

</beans>

代码说明:

  ●       id为timeBook的Bean,负责具体的业务逻辑考勤审核。

  ●       id为logProxy4的Bean,使用Spring提供的ProxyFactoryBean来实现代理,在该Bean里要定义相关的属性,包括要代理的接口、目标类以及要使用的Interceptor。

  ●       id为logThrowAdvisor的Bean,使用类RegexpMethodPointcutAdvisor来实现对切入点的配置。

  ●       属性名为patterns的值,指明只对doAuditing()方法有效。

(5)修改测试代码TestHelloWorld,使用Spring提供的代理类ProxyFactoryBean 实现日志的输出。TestHelloWorld.java的示例代码如下:

//******* TestHelloWorld.java**************

package com.gc.test;

import com.gc.action.TimeBook;

import com.gc.action.TimeBookProxy;

import com.gc.impl.TimeBookInterface;

public class TestHelloWorld {

         public static void main(String[ ] args) {

             //通过ApplicationContext获取配置文件

ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml"); 

TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy4");

timeBookProxy.doAuditing("张三");

    }

}

(6)运行测试程序,可以没有任何日志信息输出,如图5.8所示。从输出结果可以看到,没有任何日志信息输出。这是因为在doAuditing()方法里没有异常抛出,现在在doAuditing()方法里增加一个异常抛出。

图5.8  没有任何日志信息输出

(7)在TimeBook类的doAuditing()方法里增加一个异常。TimeBook.java的示例代码如下:

//******* TimeBook.java**************

package com.gc.action;

import com.gc.impl.TimeBookInterface;

public class TimeBook implements TimeBookInterface {

public void doAuditing(String name) {

//审核数据的相关程序

……   

int m = 1/0;

}

}

(8)运行测试程序,可以看到通过LogThrow类输出日志信息,如图5.9所示。

图5.9  通过LogThrow类输出日志信息

上面分别通过Spring提供的不同通知类型,实现了日志输出的实例,分别展示它们的编写和配置方式,目的还是让读者能很快地理解Spirng的通知类型。

原创粉丝点击