该实例用于在一个系统的所有方法执行过程中出现异常时,把异常信息都记录下来,另外记录每个方法的执行时间。用两个业务逻辑说明上述功能,并且一个使用Java的动态代理,一个用CGLIB代理。
- (1)定义负责异常处理的Advice为ExceptionHandler.java
- (2)定义负责记录时间的Advice为TimeHandler.java
- (3)编写实现业务逻辑的接口的类LogicInterface.java
- (4)LogicInterface类的实现Logic1.java,其将使用Java的动态代理
- (5)编写另一个没有接口的业务逻辑Logic2.java,其将使用CGLIB代理
- (6)使用自动代理定义配置文件config.xml
- (7)测试自动代理 TestAop.java
- (8)使用ProxyFactoryBean代理定义配置文件config.xml
- (9)测试 TestAop.java
(1)首先编写异常处理类、执行时间类和业务逻辑类
import java.lang.reflect.Method;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.springframework.aop.ThrowsAdvice;
//定义负责异常处理的Advice为ExceptionHandler.java
public class ExceptionHandler implements ThrowsAdvice {//Throw通知,遇到异常时输出
private Logger logger = Logger.getLogger(this.getClass().getName());
public void afterThrowing(Method method, Object[] args, Object target, Throwable subclass) throws Throwable{
logger.log(Level.INFO, args[0] + " 执行 " + method.getName() + " 时有异常抛出..." + subclass);
}
}
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
//定义负责记录时间的Advice为TimeHandler.java
public class TimeHandler implements MethodInterceptor {//Interceptor Around通知,前后都输出
private Logger logger = Logger.getLogger(this.getClass().getName());
@Override
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.getMethod().getName() + " 方法共用了 " + procTime + " 毫秒");
}
}
}
//编写实现业务逻辑的接口的类LogicInterface.java
//该接口主要用来实现使用Spring AOP的动态代理机制
public interface LogicInterface {
public void doInsert(String name);
public void doUpdate(String name);
public void doDelete(String name);
}
import com.gc.impl.LogicInterface;
//LogicInterface类的实现Logic1.java,其将使用Java的动态代理
public class Logic1 implements LogicInterface {
@Override
public void doInsert(String name) {
System.out.println("执行具体负责新增的业务逻辑...");
for(int i = 0;i < 100000000; i++) {
//模拟执行时间
}
}
@Override
public void doUpdate(String name) {
System.out.println("执行具体负责修改的业务逻辑...");
for(int i = 0;i < 200000000; i++) {
//模拟执行时间
}
}
@Override
public void doDelete(String name) {
System.out.println("执行具体负责删除的业务逻辑...");
for(int i = 0;i < 300000000; i++) {
i = i / 0;//模拟异常发生
}
}
}
//编写另一个没有接口的业务逻辑Logic2.java,其将使用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;//模拟异常发生
}
}
}
(2)自动代理:这里主要查看使用接口和不使用接口的区别
<?xml version="1.0" encoding="UTF8"?>
<!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="exceptionHandlerAdvisor" 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>
java动态代理,使用接口测试logic1:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.action.Logic2;
import com.gc.impl.LogicInterface;
//java动态代理测试logic1
public class TestAop {
public static void main(String[] args) {
ApplicationContext actx = new FileSystemXmlApplicationContext("exception_config.xml");
LogicInterface logic = (LogicInterface)actx.getBean("logic1");
try {
logic.doInsert("张三");
logic.doUpdate("李四");
logic.doDelete("王五");
} catch (Exception e) {
}
}
}
结果
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 张三 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doInsert(java.lang.String) 方法
执行具体负责新增的业务逻辑...
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 执行 doInsert 方法共用了 20 毫秒
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 李四 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doUpdate(java.lang.String) 方法
执行具体负责修改的业务逻辑...
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 执行 doUpdate 方法共用了 2 毫秒
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 王五 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doDelete(java.lang.String) 方法
执行具体负责删除的业务逻辑...
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 执行 doDelete 方法共用了 1 毫秒
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.ExceptionHandler - 王五 执行 doDelete 时有异常抛出...java.lang.ArithmeticException: / by zero
CGLIB代理,不使用接口测试logic2:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.action.Logic2;
import com.gc.impl.LogicInterface;
//CGLIB代理测试logic2
public class TestAop {
public static void main(String[] args) {
ApplicationContext actx = new FileSystemXmlApplicationContext("exception_config.xml");
Logic2 logic = (Logic2)actx.getBean("logic2");
try {
logic.doInsert("张三");
logic.doUpdate("李四");
logic.doDelete("王五");
} catch (Exception e) {
}
}
}
结果
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 张三 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doInsert(java.lang.String) 方法
执行具体负责新增的业务逻辑...
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 执行 doInsert 方法共用了 20 毫秒
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 李四 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doUpdate(java.lang.String) 方法
执行具体负责修改的业务逻辑...
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 执行 doUpdate 方法共用了 2 毫秒
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 王五 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doDelete(java.lang.String) 方法
执行具体负责删除的业务逻辑...
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.TimeHandler - 执行 doDelete 方法共用了 1 毫秒
[ INFO ] 2020-04-21 11:16:43 [main] com.gc.action.ExceptionHandler - 王五 执行 doDelete 时有异常抛出...java.lang.ArithmeticException: / by zero
(3)使用ProxyFactoryBean代理定义配置文件config.xml
<?xml version="1.0" encoding="UTF8"?>
<!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="exceptionHandlerAdvisor" 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>
<!--logic1只输出执行时间timeHandler-->
<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>
<!--logic2只输出异常信息exceptionHandler-->
<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>
logic1只执行时间日志输出,不执行异常日志输出:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.action.Logic2;
import com.gc.impl.LogicInterface;
//java动态代理测试logic1
public class TestAop {
public static void main(String[] args) {
ApplicationContext actx = new FileSystemXmlApplicationContext("exception_config.xml");
LogicInterface logic = (LogicInterface)actx.getBean("logic1Proxy");
try {
logic.doInsert("张三");
logic.doUpdate("李四");
logic.doDelete("王五");
} catch (Exception e) {
}
}
}
结果
[ INFO ] 2020-04-21 11:38:23 [main] com.gc.action.TimeHandler - 张三 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doInsert(java.lang.String) 方法
执行具体负责新增的业务逻辑...
[ INFO ] 2020-04-21 11:38:23 [main] com.gc.action.TimeHandler - 执行 doInsert 方法共用了 22 毫秒
[ INFO ] 2020-04-21 11:38:23 [main] com.gc.action.TimeHandler - 李四 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doUpdate(java.lang.String) 方法
执行具体负责修改的业务逻辑...
[ INFO ] 2020-04-21 11:38:23 [main] com.gc.action.TimeHandler - 执行 doUpdate 方法共用了 1 毫秒
[ INFO ] 2020-04-21 11:38:23 [main] com.gc.action.TimeHandler - 王五 开 始 执 行 public abstract void com.gc.impl.LogicInterface.doDelete(java.lang.String) 方法
执行具体负责删除的业务逻辑...
[ INFO ] 2020-04-21 11:38:23 [main] com.gc.action.TimeHandler - 执行 doDelete 方法共用了 0 毫秒
logic2只执行异常日志输出,不执行时间日志输出:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.action.Logic2;
import com.gc.impl.LogicInterface;
//CGLIB代理测试logic2
public class TestAop {
public static void main(String[] args) {
ApplicationContext actx = new FileSystemXmlApplicationContext("exception_config.xml");
Logic2 logic = (Logic2)actx.getBean("logic2Proxy");
try {
logic.doInsert("张三");
logic.doUpdate("李四");
logic.doDelete("王五");
} catch (Exception e) {
}
}
}
结果
执行具体负责新增的业务逻辑...
执行具体负责修改的业务逻辑...
执行具体负责删除的业务逻辑...
[ INFO ] 2020-04-21 11:45:10 [main] com.gc.action.ExceptionHandler - 王五 执行 doDelete 时有异常抛出...java.lang.ArithmeticException: / by zero