上一篇博文用Java动态代理实现了一个简单应用场景,现在来看一下在Spring中如何采用Java动态代理完成同样的应用场景。
一 代码
应用场景:度量一段计算10000000次浮点乘法的代码的运行时间。
1.1 抽象角色ComputeInterface
public interface ComputeInterface { void compute(); }
1.2 真实角色RealCompute
public class RealCompute implements ComputeInterface { @Override public void compute() { double result=1.0; System.out.println("正在进行10000000次浮点乘法..."); for(int i=0;i<10000000;i++){ result*=1.123345; } } }
1.3 调用处理器TimeHandler——继承于org.aopalliance.intercept.MethodInterceptor
public class TimeHandler implements MethodInterceptor{ @Override public Object invoke(MethodInvocation mInvocation) throws Throwable { System.out.println("开始运行..."); long startTime=System.currentTimeMillis(); Object result=mInvocation.proceed(); long endTime=System.currentTimeMillis(); System.out.println("运行结束,运行时间为:"+ (endTime-startTime)); return result; } }
1.4 配置文件AOP.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="timeHandler" class="aop.proxy.sse.ustc.TimeHandler"/> <bean id="realCompute" class="aop.proxy.sse.ustc.RealCompute"/> <bean id="timeProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>aop.proxy.sse.ustc.ComputeInterface</value> </property> <property name="target"> <ref bean="realCompute"/> </property> <property name="interceptorNames"> <list> <value>timeHandler</value> </list> </property> </bean> </beans>
1.5 客户类TestCompute
public class TestCompute { public static void main(String[] args) { ApplicationContext aContext=new ClassPathXmlApplicationContext("AOP.xml"); ComputeInterface timeProxy=(ComputeInterface)aContext.getBean("timeProxy"); timeProxy.compute(); } }
运行结果如下:
开始运行...
正在进行10000000次浮点乘法...
运行结束,运行时间为:27
1.6 分析
与直接采用Java动态代理相比,Spring AOP无需在调用处理器中指定被代理对象,而通过配置文件注入该实例。
二 进一步
场景:现在想在开始程序之前先记录是谁运行了程序,运行程序完毕提示谁结束了运行程序。
2.1 添加调用处理器NameHandler
public class NameHandler implements MethodInterceptor { String name="小明"; @Override public Object invoke(MethodInvocation mInvocation) throws Throwable { System.out.println(name+"运行了程序!"); Object result=mInvocation.proceed(); System.out.println(name+"运行程序完毕!"); return result; } }
2.2 修改配置文件AOP.xml
在上述配置文件<beans>标签中添加如下:
<bean id="nameHandler" class="aop.proxy.sse.ustc.NameHandler"/> <bean id="nameProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>aop.proxy.sse.ustc.ComputeInterface</value> </property> <property name="target"> <ref bean="timeProxy"/> </property> <property name="interceptorNames"> <list> <value>nameHandler</value> </list> </property> </bean>
2.3 修改测试类
public class TestCompute { public static void main(String[] args) { /* ApplicationContext aContext=new ClassPathXmlApplicationContext("AOP.xml"); ComputeInterface timeProxy=(ComputeInterface)aContext.getBean("timeProxy"); timeProxy.compute(); */ ApplicationContext aContext=new ClassPathXmlApplicationContext("AOP.xml"); ComputeInterface timeProxy=(ComputeInterface)aContext.getBean("nameProxy"); timeProxy.compute(); } }
运行结果:
小明运行了程序!
开始运行...
正在进行10000000次浮点乘法...
运行结束,运行时间为:45
小明运行程序完毕!