日期:2014-05-16 浏览次数:21015 次
AOP是一种将通用逻辑与具体业务分离的技术,能够弥补OO在横向代码复用不足的问题,很好的实现separation of concerns (SoC)。缓存是改善系统性能的一种常用技术,采取以空间换时间的策略。缓存就是与具体业务无关的,如果我们设计一个缓存框架,那么应该是可插拔的,对系统业务代码无侵入的,这很符合AOP的适用场景。我们的项目采用了Ehcache缓存框架作为底层支撑,采用Spring框架的AOP进行方法拦截,将耗时方法的返回结果,进行缓存。现在我们使用spring的aop模拟这种实现。
首先假设我们有一个已经编写好的,比较耗时的类
package net.aty.dao; public class DaoImpl { public String query(int id) { // 模拟耗时的数据库查询操作 try { System.out.println("query begin..."); Thread.sleep(100 * id); System.out.println("query over..."); } catch (InterruptedException e) { e.printStackTrace(); } return "result:" + id * 10; } }
package net.aty.cache; import java.util.HashMap; import java.util.Map; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; public class CacheQueryResult { private Map<String, Object> buffer = new HashMap<String, Object>(); public Object around(ProceedingJoinPoint point) throws Throwable { String key = uniqueKey(point); Object returnValue = buffer.get(key); if(returnValue != null) { return returnValue; } Object object = point.proceed(); buffer.put(key, object); return object; } private String uniqueKey(ProceedingJoinPoint point) { Object target = point.getTarget(); Signature signature = point.getSignature(); String methodSignature = signature.toString(); String key = target.hashCode() + methodSignature; return key; } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <!-- 需要被拦截的目标对象 --> <bean id="dao" class="net.aty.dao.DaoImpl"></bean> <!-- 方法拦截器和环绕增强--> <bean id="cacheInterceptor" class="net.aty.cache.CacheQueryResult"></bean> <aop:config proxy-target-class="true"> <aop:pointcut id="cachePointcut" expression="execution(public * net.aty.dao.DaoImpl.*(..))" /> <aop:aspect id="cacheAspect" ref="cacheInterceptor"> <aop:around method="around" pointcut-ref="cachePointcut" /> </aop:aspect> </aop:config> </beans>
package net.aty; import net.aty.dao.DaoImpl; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestMain { private static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "spring.xml"); public static void main(String[] args) { for (int i = 0; i < 3; i++) { testDao(); }