Spring AOP——轻松实现代理

本文依然参考夏昕的Spring开发指南(下载自满江红)。

这里,我想先说下“满江红开源”(http://wiki.redsaga.com/)。这是我见识过国内最好的开源组织。满江红的页面非常简洁,但是提供的东西都是非常实用的。在主页下端还提供了到JavaEye的连接。因为本身我觉着JavaEye就是一个很好的社区,所以进一步说明满江红是一个很不错的组织。

转入正题,昨天写了关于Java动态代理的东东,但是从实现过程来看,稍显复杂。从原始类得到代理类的过程,很容易让人迷惑。使用Spring的AOP可以很简单的实现动态代理,并且得到代理对象的过程完全由Spring完成,我们做的只是写xml配置。还有另外一点,就是如果使用JDK的动态代理,那么被代理类必须实现接口。但是Spring的AOP没有这样的限制,它的代理实现有两种方式,JDK的动态代理和CGLIB(在后面的文章中有介绍)。下面是个Spring的AOP的例子,有JDK的动态代理和CGLIB两个版本,用AOP记录函数的执行时间。

 

首先是JDK动态代理版本。

 

接口test.quqtalk.spring.aop. ITest

 

package test.quqtalk.spring.aop;

public interface ITest {
	public abstract void doTest();

	public abstract void executeTest();
}

  接口的实现类:

 

 

package test.quqtalk.spring.aop;

public class Test implements ITest {
	public void doTest() {
		for (int i = 0; i < 10000; i++) {
		}
	}

	public void executeTest() {
		for (int i = 0; i < 25000; i++) {
		}
	}
}

 

  AOP的逻辑处理类:

 

package test.quqtalk.spring.aop;

import java.io.Serializable;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MethodTimeCostInterceptor implements MethodInterceptor,
		Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5916297666638680535L;
	protected static final Log logger = LogFactory
			.getLog(MethodTimeCostInterceptor.class);

	public Object invoke(MethodInvocation invocation) throws Throwable {
		long time = System.currentTimeMillis();
		Object rval = invocation.proceed();
		time = System.currentTimeMillis() - time;
		System.out.println("Method Cost Time => " + time + " ms");
		return rval;
	}

}

 

Spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
	<bean id="myPointcutAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice">
			<ref local="MyInterceptor"/>
		</property>
		<property name="patterns">
			<list>
				<value>.*do.*</value>
				<value>.*execute.*</value>
			</list>
		</property>
	</bean>
	<bean id="MyInterceptor"
		class="test.quqtalk.spring.aop.MethodTimeCostInterceptor"/>
	
	<bean id="myAOPProxy"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces">
			<value>test.quqtalk.spring.aop.ITest</value>
		</property>
		
		<property name="target">
			<ref local="test"/>
		</property>
		
		<property name="interceptorNames">
			<value>myPointcutAdvisor</value>
		</property>
	</bean>
	
	<bean id="test" class="test.quqtalk.spring.aop.Test"/>
</beans>

  测试类:

package test.quqtalk.spring.aop;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
				"test/quqtalk/spring/aop/app.xml");
		//这里强制转换成ITest
		ITest test = (ITest) ctx.getBean("myAOPProxy");

		test.doTest();
		test.executeTest();
	}
}

 

然后,是CGLIB版本。

 

  被代理类test.quqtalk.spring.aop.Test,注意这里没有实现任何接口:

 

package test.quqtalk.spring.aop;

public class Test{
	public void doTest() {
		for (int i = 0; i < 10000; i++) {
		}
	}

	public void executeTest() {
		for (int i = 0; i < 25000; i++) {
		}
	}
}

 

  处理逻辑跟JDK动态代理版本相同:

package test.quqtalk.spring.aop;

import java.io.Serializable;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MethodTimeCostInterceptor implements MethodInterceptor,
		Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5916297666638680535L;
	protected static final Log logger = LogFactory
			.getLog(MethodTimeCostInterceptor.class);

	public Object invoke(MethodInvocation invocation) throws Throwable {
		long time = System.currentTimeMillis();
		Object rval = invocation.proceed();
		time = System.currentTimeMillis() - time;
		System.out.println("Method Cost Time => " + time + " ms");
		return rval;
	}

}

  配置文件:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
	<bean id="myPointcutAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice">
			<ref local="MyInterceptor"/>
		</property>
		<property name="patterns">
			<list>
				<value>.*do.*</value>
				<value>.*execute.*</value>
			</list>
		</property>
	</bean>
	<bean id="MyInterceptor"
		class="test.quqtalk.spring.aop.MethodTimeCostInterceptor"/>
	
	<bean id="myAOPProxy"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		
		<property name="proxyTargetClass">
			<value>true</value>
		</property>
		
		<property name="target">
			<ref local="test"/>
		</property>
		
		<property name="interceptorNames">
			<value>myPointcutAdvisor</value>
		</property>
	</bean>
	
	<bean id="test" class="test.quqtalk.spring.aop.Test"/>
</beans>

 

  测试程序:

 

package test.quqtalk.spring.aop;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
				"test/quqtalk/spring/aop/app.xml");
		//这里强制转换成Test
		Test test = (Test) ctx.getBean("myAOPProxy");

		test.doTest();
		test.executeTest();
	}
}

 

运行后控制台都会打出:

Method Cost Time => 0 ms

Method Cost Time => 0 ms

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值