一个用Spring AOP实现异常处理和记录程序执行时间的实例--邵京国
来源:互联网 发布:单片机晶振电路的作用 编辑:程序博客网 时间:2024/05/29 23:46
虽然前面也给出了Spring AOP的一些实例,但因为主要目的是为了介绍Spring的知识点,不一定会很完整,下面笔者就通过一个完整的用Spring AOP实现异常处理和记录程序执行时间的实例来展示使用Spring AOP的整个过程。
5.11.1 异常处理和记录程序执行时间的实例简介
这个实例主要用于在一个系统的所有方法执行过程中出现异常时,把异常信息都记录下来,另外记录每个方法的执行时间。用两个业务逻辑来说明上述功能,这两个业务逻辑首先使用Spring AOP的自动代理功能,然后一个用Java的动态代理,一个用CGLIB代理。
实现思路是:仍然使用前面所建的Java工程myApp,首先定义负责异常处理的Advice为ExceptionHandler.java,定义记录程序执行时间的Advice为TimeHandler.java,接着定义业务逻辑接口LogicInterface.java,编写实现业务逻辑接口的类Logic1.java,该业务逻辑在Spring AOP中使用Java的动态代理,编写另一个业务逻辑Logic2.java不实现业务逻辑接口,该业务逻辑在Spring AOP中使用CGLIB代理,然后使用自动代理定义配置文件config.xml,最后编写测试程序TestAop.java,执行它并查看输出结果。下面就一步一步来实现这个实例。
5.11.2 定义负责异常处理的Advice为ExceptionHandler.java
在myApp工程的com.gc.action包中新建ExceptionHandler.java,该类主要负责当程序执行过程中出现异常时,把异常信息都记录下来。而Spring提供的通知类型中Throw通知可以实现这个功能,因此这里使用Throw通知类型来实现Advice,类ExceptionHandler必须实现ThrowsAdvice接口,重写afterThrowing()方法。ThrowsAdvice.java的示例代码如下:
//******* ExceptionHandler.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通知类型来实现Advice
public class ExceptionHandler 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] + " 执行 " + method.getName() + " 时有异常抛出...." + subclass);
}
}
代码说明:
● 必须重写afterThrowing()方法。
● 当程序有异常发生时,就会输出“×××执行×××方法时有异常抛出”和具体异常的记录信息。
5.11.3 定义记录程序执行时间的Advice为TimeHandler.java
在myApp工程的com.gc.action包中新建TimeHandler.java,该类主要负责记录每个方法的执行时间,而Spring提供的通知类型中Around通知可以实现这个功能,因此这里使用Around通知类型来实现Advice,类TimeHandler必须实现MethodInterceptor接口,重写invoke()方法。TimeHandler.java的示例代码如下:
//******* TimeHandler.java**************
package com.gc.action;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
//类TimeHandler必须实现MethodInterceptor接口
public class TimeHandler implements MethodInterceptor{
private Logger logger = Logger.getLogger(this.getClass().getName());
//重写invoke()方法
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long procTime = System.currentTimeMillis();
logger.log(Level.INFO, methodInvocation.getArguments()[0] + " 开始执行 " + methodInvocation.getMethod() + " 方法");
try {
Object result = methodInvocation.proceed();
return result;
}
finally {
//计算执行时间
procTime = System.currentTimeMillis() - procTime;
logger.log(Level.INFO, methodInvocation.getArguments()[0] + " 执行 " + methodInvocation.getMethod() + " 方法结束");
logger.log(Level.INFO, "执行 " + methodInvocation.getMethod().getName() + " 方法共用了 " + procTime + "毫秒");
}
}
}
代码说明:
● 必须重写invoke()方法。
● 当有方法执行时,就会输出“×××在什么时间开始执行×××方法”、“×××在什么时间执行×××方法结束”和“执行×××方法共用了×××毫秒”的记录信息。
5.11.4 定义业务逻辑接口LogicInterface.java
在myApp工程的com.gc.impl包中新建接口LogicInterface.java,该接口主要用来实现使用Spring AOP的动态代理机制,在这个接口里共定义了3个方法——新增、修改和删除。LogicInterface.java的示例代码如下:
//******* LogicInterface.java**************
package com.gc.impl;
//该接口主要用来实现使用Spring AOP的动态代理机制
public interface LogicInterface {
public void doInsert(String name);
public void doUpdate(String name);
public void doDelete(String name);
}
5.11.5 编写实现业务逻辑接口的类Logic1.java
在myApp工程的com.gc.action包中新建业务逻辑类Logic1.java,该类主要负责具体的业务逻辑,这个类实现了前面定义的接口LogicInterface,并重写了接口LogicInterface定义的3个方法——新增、修改和删除,用来实现使用Spring AOP的动态代理机制,并在删除方法里增加一个“i = i / 0”,用来模拟异常的发生。Logic1.java的示例代码如下:
//******* Logic1.java**************
package com.gc.action;
import com.gc.impl.LogicInterface;
//实现这个接口
public class Logic1 implements LogicInterface{
//负责新增
public void doInsert(String name){
System.out.println("执行具体负责新增的业务逻辑…");
for (int i = 0; i < 100000000; i++) {
//模拟执行时间
}
}
//负责修改
public void doUpdate(String name){
System.out.println("执行具体负责修改的业务逻辑…");
for (int i = 0; i < 200000000; i++) {
//模拟执行时间
}
}
//负责删除
public void doDelete(String name){
System.out.println("执行具体负责删除的业务逻辑…");
for (int i = 0; i < 300000000; i++) {
i = i / 0;//模拟异常发生
}
}
}
5.11.6 编写一个不实现业务逻辑接口的类Logic2.java
在myApp工程的com.gc.action包中新建业务逻辑类Logic2.java,该类主要负责具体的业务逻辑——新增、修改和删除,这个类不实现前面定义的接口LogicInterface,用来实现使用Spring AOP的CGLIB代理机制,并在删除方法里增加一个“i = i / 0”,用来模拟异常的发生。Logic2.java的示例代码如下:
//******* Logic2.java**************
package com.gc.action;
//该类采用CGLIB代理机制
public class Logic2 {
//负责新增
public void doInsert(String name){
System.out.println("执行具体负责新增的业务逻辑…");
for (int i = 0; i < 100000000; i++) {
//模拟执行时间
}
}
//负责修改
public void doUpdate(String name){
System.out.println("执行具体负责修改的业务逻辑…");
for (int i = 0; i < 200000000; i++) {
//模拟执行时间
}
}
//负责删除
public void doDelete(String name){
System.out.println("执行具体负责删除的业务逻辑…");
for (int i = 0; i < 300000000; i++) {
i = i / 0;//模拟异常发生
}
}
}
5.11.7 使用自动代理定义配置文件config.xml
在myApp根目录下,新建一个Spring的配置文件exception_config.xml,主要用来使用Spring的自动代理功能,代理本系统所有的程序。exception_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="logic1" class="com.gc.action.Logic1"/>
<bean id="logic2" class="com.gc.action.Logic2"/>
<!--设定为自动代理-->
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!--负责记录有异常发生时的信息-->
<bean id="exceptionHandler" class="com.gc.action.ExceptionHandler"/>
<bean id="exceptionHandlereAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="exceptionHandler"/>
</property>
<!--对指定类的任何方法有效-->
<property name="patterns">
<value>.*.*</value>
</property>
</bean>
<!--负责记录方法的记录时间-->
<bean id="timeHandler" class="com.gc.action.TimeHandler"/>
<bean id="timeHandlerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="timeHandler"/>
</property>
<!--对指定类的任何方法有效-->
<property name="patterns">
<value>.*.*</value>
</property>
</bean>
</beans>
5.11.8 编写测试类Logic1的程序TestAop.java
在myApp工程的com.gc.test包中新建测试类TestAop.java,该类主要负责对前面程序的测试和演示,这里先编写对业务逻辑Logic1.java的演示。TestAop.java的示例代码如下:
//******* TestAop.java**************
package com.gc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.impl.LogicInterface;
public class TestAop {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//通过ApplicationContext获取配置文档
ApplicationContext actx=new FileSystemXmlApplicationContext("exception_config.xml");
LogicInterface logic = (LogicInterface)actx.getBean("logic1");
//模拟执行新增、修改、删除方法
try {
logic.doInsert("张三");
logic.doUpdate("李四");
logic.doDelete("王五");
} catch (Exception ex) {
}
}
}
5.11.9 输出自动代理时类Logic1异常处理和记录程序执行时间的信息
运行测试程序,即可看到记录Logic1.java中每个方法执行时间和在删除方法里捕获的异常的信息,如图5.16所示。
图5.16 记录Logic1.java中每个方法执行时间和在删除方法里捕获的异常信息
5.11.10 编写测试类Logic2的程序TestAop.java
上面主要是针对业务逻辑Logic1.java的测试,所以在记录的信息中,类名显示的是Logic1实现的接口LogicInterface的名称,对于业务逻辑Logic2.java的测试,需要修改测试代码TestAop.java。TestAop.java的示例代码如下:
//******* TestAop.java**************
package com.gc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.action.Logic2;
public class TestAop {
public static void main(String[ ] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//通过ApplicationContext获取配置文档
ApplicationContext actx=new FileSystemXmlApplicationContext("exception_config.xml");
Logic2 logic2 = (Logic2)actx.getBean("logic2");
//模拟执行新增、修改和删除方法
try {
logic2.doInsert("张三");
logic2.doUpdate("李四");
logic2.doDelete("王五");
} catch (Exception ex) {
}
}
}
5.11.11 输出自动代理时类Logic2异常处理和记录程序执行时间的信息
运行测试程序,即可看到记录Logic2.java中每个方法执行时间和在删除方法里捕获的异常的信息,如图5.17所示。
图5.17 记录Logic2.java中每个方法执行时间和在删除方法里捕获的异常信息
上面主要是针对业务逻辑Logic2.java的测试,所以在记录的信息中,类名显示的是Logic2的名称。这是使用接口和不使用接口时显示信息的主要区别。
以上示例使用的是Spring AOP的自动代理,那对于使用Spring AOP的动态代理和CGLIB代理来说,应该怎么实现呢?下面就来讲解使用ProxyFactoryBean实现动态代理和CGLIB代理。
5.11.12 使用ProxyFactoryBean代理定义配置文件config.xml
改写Spring的配置文件exception_config.xml,主要用来使用Spring的ProxyFactoryBean代理功能,对Logic1.java只记录程序执行时间,不捕获发生的异常,对Logic2.java只捕获发生的异常,不记录程序执行时间,去掉前面的自动代理。exception_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="logic1" class="com.gc.action.Logic1"/>
<bean id="logic2" class="com.gc.action.Logic2"/>
<!--设定为自动代理-->
<!--负责记录有异常发生时的信息-->
<bean id="exceptionHandler" class="com.gc.action.ExceptionHandler"/>
<bean id="exceptionHandlereAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="exceptionHandler"/>
</property>
<!--对指定类的任何方法有效-->
<property name="patterns">
<value>.*.*</value>
</property>
</bean>
<!--负责记录方法的记录时间-->
<bean id="timeHandler" class="com.gc.action.TimeHandler"/>
<bean id="timeHandlerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="timeHandler"/>
</property>
<!--对指定类的任何方法有效-->
<property name="patterns">
<value>.*.*</value>
</property>
</bean>
<bean id="logic1Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.gc.impl.LogicInterface</value>
</property>
<property name="target">
<ref bean="logic1"/>
</property>
<!--指定代理类-->
<property name="interceptorNames">
<list>
<value>timeHandlerAdvisor</value>
</list>
</property>
</bean>
<bean id="logic2Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="target">
<ref bean="logic2"/>
</property>
<!--指定代理类-->
<property name="interceptorNames">
<list>
<value>exceptionHandler</value>
</list>
</property>
</bean>
</beans>
5.11.13 编写测试类Logic1的程序TestAop.java
这里先改写对业务逻辑Logic1.java的演示。TestAop.java的示例代码如下:
//******* TestAop.java**************
package com.gc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.impl.LogicInterface;
public class TestAop {
public static void main(String[ ] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//通过ApplicationContext获取配置文档
ApplicationContext actx=new FileSystemXmlApplicationContext("exception_config.xml");
LogicInterface logic = (LogicInterface)actx.getBean("logic1Proxy");
//模拟执行新增、修改和删除方法
try {
logic.doInsert("张三");
logic.doUpdate("李四");
logic.doDelete("王五");
} catch (Exception ex) {
}
}
}
5.11.14 输出ProxyFactoryBean代理时类Logic1记录程序执行时间的信息
运行测试程序,即可看到记录Logic1.java中每个方法执行时间的信息,如图5.18所示。
图5.18 记录Logic1.java中每个方法执行时间的信息
5.11.15 编写测试类Logic2的程序TestAop.java
上面主要是针对业务逻辑Logic1.java的测试,所以在记录的信息中,只显示了每个方法的执行时间,而没有捕获删除方法抛出的异常信息,对于业务逻辑Logic2.java的测试,使其只捕获删除方法抛出的信息,而不记录每个方法执行的时间,需要修改测试代码TestAop.java。TestAop.java的示例代码如下:
//******* TestAop.java**************
package com.gc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.action.Logic2;
public class TestAop {
public static void main(String[ ] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//通过ApplicationContext获取配置文档
ApplicationContext actx=new FileSystemXmlApplicationContext("exception_config.xml");
Logic2 logic2 = (Logic2)actx.getBean("logic2Proxy ");
//模拟执行新增、修改和删除方法
logic2.doInsert("张三");
logic2.doUpdate("李四");
logic2.doDelete("王五");
}
}
5.11.16 输出ProxyFactoryBean代理时类Logic2异常处理的信息
运行测试程序,即可看到记录Logic2.java中在删除方法里捕获的异常的信息,如图5.19所示。
图5.19 记录Logic2.java中在删除方法里捕获的异常信息
上面主要是针对业务逻辑Logic2.java的测试,所以在记录的信息中,只捕获删除方法抛出的异常信息,而不记录每个方法执行的时间。
- 一个用Spring AOP实现异常处理和记录程序执行时间的实例--邵京国
- 5.11 一个用Spring AOP实现异常处理和记录程序执行时间的实例
- 一个用Spring AOP实现异常处理和记录程序执行时间的实例(一)
- 一个用Spring AOP实现异常处理和记录程序执行时间的实例(二)
- 用Spring AOP实现异常处理和记录程序执行时间
- 使用Spring的AOP实现接口方法执行时间记录
- AspectJ spring aop 记录某些类中方法执行时间实例
- AspectJ spring aop 记录某些类中方法执行时间实例
- 利用Spring AOP实现业务和异常日志记录
- Spring AOP实践--记录类方法执行时间
- spring boot aop 记录方法执行时间
- Spring AOP - 注解实现统计service中方法的执行时间
- spring aop 异常记录
- Spring AOP切面实现:异常处理
- 计算一个程序的执行时间和定时器
- Spring Aop异常处理
- spring aop 实现方法执行时间监控
- spring aop 实现方法执行时间监控
- 获取程序资源 Resources
- 聆听英特尔中国前总裁陈朝益谈5%
- System.load 和 System.loadLibrary详解
- 5分钟踢进TDD之门
- 递归拷贝所有子目录
- 一个用Spring AOP实现异常处理和记录程序执行时间的实例--邵京国
- 命令行参数解析(1)
- OpenID
- 八叉树(octree)简介(zz)
- 无法获取DataSet删除行的值的问题
- JUnit 入門(六) - 測試設備(Test fixture)
- arcsde9.2中text的存储类型问题(unicode,varchar and nvarchar)
- Web Beans Public Review Draft released
- GFS与RHCS安装记录