AOP+Ehcache 缓存框架

AOP+Ehcache 实现缓存功能

设计思路:查询数据,通过AOP拦截需要缓存的方法,在方法进入之前进入拦截器,通过包、类、方法名称作为key获取当前缓存对象结果,如果为空,则执行真正的方法,如果有缓存对象,则直接返回。删除和修改数据,每次都在此之前调用拦截器方法清除相关缓存对象。

1.需要引入AOP和Ehcache相关Jar文件

2.编写切面类里面写上拦截时的业务逻辑


import java.io.Serializable;
import java.util.List;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
*
* 类功能描述:AOP+Ehcache 拦截需要缓存的方法,插入点方法执行前后
*
* @author <a href="mailto:qingyu.meng21@gmail.com">mengqingyu </a>
* @version $Id: codetemplates.xml,v 1.1 2009/03/06 01:13:01 mengqingyu Exp $
* Create: 2011-12-12 下午04:27:44
*/
public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean
{
private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);

private Cache cache;

public void setCache(Cache cache) {
this.cache = cache;
}

public MethodCacheInterceptor() {
super();
}

/**
* 拦截Service/DAO的方法,并查找该结果是否存在,如果存在就返回cache中的值,
* 否则,返回数据库查询结果,并将查询结果放入cache
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result;
String cacheKey = getCacheKey(invocation.getThis().getClass().getName()
, invocation.getMethod().getName(), invocation.getArguments());
Element element = cache.get(cacheKey);
logger.warn("检查缓存:" + cacheKey);
if (element == null) {
logger.warn("创建缓存......");
result = invocation.proceed();
element = new Element(cacheKey, (Serializable) result);
cache.put(element);
}
List list = cache.getKeys();
return element.getValue();
}

/**
*
* @function:获得cache key的方法,cache key是Cache中一个Element的唯一标识
* cache key包括 包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser
* @param targetName
* @param methodName
* @param arguments
* @return
* @author: mengqingyu 2011-12-12 下午04:35:21
*/
private String getCacheKey(String targetName, String methodName, Object[] arguments) {
StringBuilder sb = new StringBuilder();
sb.append(targetName).append(".").append(methodName);
if (arguments != null) {
for(Object o:arguments){
sb.append(".").append(o);
}
}
return sb.toString();
}

/**
* implement InitializingBean,检查cache是否为空
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "缓存未初始化");
}
}

package com.berheley.bi.aop;

import java.lang.reflect.Method;
import java.util.List;

import net.sf.ehcache.Cache;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
*
* 类功能描述:AOP+Ehcache 拦截需要缓存的方法,插入点方法执行之后
*
* @author <a href="mailto:qingyu.meng21@gmail.com">mengqingyu </a>
* @version $Id: codetemplates.xml,v 1.1 2009/03/06 01:13:01 mengqingyu Exp $
* Create: 2011-12-12 下午04:27:44
*/
public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean
{
private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class);

private Cache cache;

public void setCache(Cache cache) {
this.cache = cache;
}

public MethodCacheAfterAdvice() {
super();
}

/**
* 拦截Service/DAO的方法,并查找该结果是否存在,如果存在则删除结果,
* 否则忽略,此方法为了保证更新数据库同时同步缓存
*/
@Override
public void afterReturning(Object arg, Method method, Object[] arguments,
Object obj) throws Throwable {
String className = obj.getClass().getName();
List<String> list = cache.getKeys();
for(String cacheKey:list){
if(cacheKey.startsWith(className)){
cache.remove(cacheKey);
logger.debug("删除缓存:" + cacheKey);
}
}
}

/**
* implement InitializingBean,检查cache是否为空
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "缓存未初始化");
}
}


3.配置文件中配置AOP和类的实例化

<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">

<!-- AOP+Ehcache by mengqingyu-->

<!-- 引用ehCache的配置 -->
<bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation">
<value>classpath:ehcache.xml</value>
</property>
</bean>

<!-- 定义ehCache的工厂,并设置所使用的Cache name 如找不到则使用默认缓存配置defaultCache-->
<bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="defaultCacheManager"/>
</property>
<property name="cacheName">
<value>systemCache</value>
</property>
</bean>

<!-- find/create cache拦截器 -->
<bean id="methodCacheInterceptor" class="com.berheley.bi.aop.MethodCacheInterceptor">
<property name="cache">
<ref local="ehCache" />
</property>
</bean>

<!-- find/create cache拦截器 -->
<bean id="methodCacheAfterAdvice" class="com.berheley.bi.aop.MethodCacheAfterAdvice">
<property name="cache">
<ref local="ehCache" />
</property>
</bean>

<!-- 自动代理 -->
<aop:config>
<!-- 这里可添加多个切入点 -->
<aop:advisor pointcut="execution(* com.berheley.bi.report.service.impl.SummaryReportServiceImpl.getSource*(..))" advice-ref="methodCacheInterceptor" />
<aop:advisor pointcut="execution(* com.berheley.bi.report.service.impl.SummaryReportServiceImpl.getPrefixAndSuffix*(..))" advice-ref="methodCacheAfterAdvice" />
</aop:config>
</beans>


4.引入ehcache.xml文件

<!-- AOP+Ehcache by mengqingyu-->

<!--
diskStore 当内存缓存数量超过设置数量时,将数据写到硬盘中,path为硬盘相对路径
maxElementsInMemory 缓存中最大允许创建的对象数
eternal 缓存中对象是否为永久,如果true过期设置将无效
timeToIdleSeconds 自最后读取开始有效时间
timeToLiveSeconds 自创建开始有效时间
overflowToDisk 内存不足时是否启用磁盘缓存
-->
<ehcache>
<diskStore path="java.io.tmpdir"/>

<defaultCache
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"/>

<cache name="systemCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="259200000"
timeToLiveSeconds="259200000"
overflowToDisk="true"/>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值