spring + ehcache 整合

一:ehcache 简介

  ehCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider
  类似于做了数据库的一个备份,一定要注意使用ehcache时的数据脏读

二:spring 需要的知识点
  1 spring AOP 应用的几种方式:ProxyFactoryBean 动态代理,2.0版本之前;<aop> 标签 2.0版本之后
  2 spring 获取接入点信息:JoinPoint 和 ProceedingJoinPoint(限于环绕通知使用)

三:使用

  1 ehcache 配置:

<?xml version="1.0" encoding="UTF-8"?>
  
  <ehcache>  
    <diskStore path="c:\\myapp\\cache"/>  
    <defaultCache  
        maxElementsInMemory="1"  
        eternal="false"  
        timeToIdleSeconds="120"  
        timeToLiveSeconds="120"  
        overflowToDisk="true"  
        />  
  <cache name="SYSTEM_CACHE"  
        maxElementsInMemory="11"  
        eternal="false"  
        timeToIdleSeconds="300000"  
        timeToLiveSeconds="600000"  
        overflowToDisk="true"  
        />  
</ehcache>       
             

  2 spring 配置文件:

<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:jms="http://www.springframework.org/schema/jms" xmlns:security="http://www.springframework.org/schema/security"
    xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
        http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
        http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">

    <!-- 激活annotation功能 -->
    <context:annotation-config />
    <!-- 开启使用@Transactional注解方式 -->
    <tx:annotation-driven transaction-manager="transactionManager"
        proxy-target-class="true" />
    <context:component-scan base-package="ehcache.*"
        scoped-proxy="targetClass">
    </context:component-scan>

    <!-- DataSource -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
        <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521/orcl" />
        <property name="user" value="oracle" />
        <property name="password" value="oracle" />
        <!-- 连接池其他配置 -->
        <property name="minPoolSize" value="2" />
        <property name="maxPoolSize" value="5" />
        <property name="maxIdleTime" value="60" />
        <property name="acquireIncrement" value="3" />
        <property name="maxStatements" value="10" />
        <property name="initialPoolSize" value="2" />
        <property name="idleConnectionTestPeriod" value="900" />
        <property name="numHelperThreads" value="10" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="cacheDao" class="ehcache.integration.dao.CacheDao">
        <property name="jdbcTemplate" ref="jdbcTemplate" />
    </bean>
    <bean id="cacheService" class="ehcache.integration.service.CacheService">
        <property name="cacheDao" ref="cacheDao" />
    </bean>

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

    <!-- 定义ehCache的工厂,并设置所使用的Cache name -->
    <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
        <property name="cacheManager">
            <ref local="defaultCacheManager" />
        </property>
        <property name="cacheName">
            <value>SYSTEM_CACHE</value>
        </property>
    </bean>

    <!-- 切面 -->
    <bean id="aspectClass" class="ehcache.integration.interceptor.MethodCacheInterceptor">
        <property name="cache">
            <ref local="ehCache" />
        </property>
    </bean>
    
    <aop:config proxy-target-class="true">
        <aop:aspect ref="aspectClass">
        <aop:pointcut expression="execution(* ehcache.integration.service.*Service.*(..))" id="servicePointcut"/>
        <aop:around method="doIntercept" pointcut-ref="servicePointcut"/>
        </aop:aspect>
    </aop:config>

</beans>

 

  3 切面及通知方法定义:

  

package ehcache.integration.interceptor;

import java.io.Serializable;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.aspectj.lang.ProceedingJoinPoint;

public class MethodCacheInterceptor {

    private Cache cache;

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

    /** 
     * 拦截Service/DAO的方法,并查找该结果是否存在,如果存在就返回cache中的值, 
     * 否则,返回数据库查询结果,并将查询结果放入cache 
     * 1) JoinPoint 
     * java.lang.Object[] getArgs():获取连接点方法运行时的入参列表; 
     * Signature getSignature() :获取连接点的方法签名对象; 
     * java.lang.Object getTarget() :获取连接点所在的目标对象; 
     * java.lang.Object getThis() :获取代理对象本身; 
     * 2)ProceedingJoinPoint (只能用于环绕通知)
     * ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法: 
     * java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法; 
     * java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法
     * @throws Throwable 
     */
    public Object doIntercept(ProceedingJoinPoint joinPoint) throws Throwable {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();

        String cacheKey = getCacheKey(targetName, methodName, arguments);
        Element element = cache.get(cacheKey);
        
        Object result = null;
        if (element == null) {
            result = joinPoint.proceed();  
            element = new Element(cacheKey, (Serializable)result);  
            cache.put(element);  
        }
        return element.getValue();
    }

    /** 
     * 获得cache key的方法,cache key是Cache中一个Element的唯一标识 
     * cache key包括 包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser 
     */
    private String getCacheKey(String targetName, String methodName, Object[] arguments) {
        StringBuffer sb = new StringBuffer();
        sb.append(targetName).append(".").append(methodName);
        if ((arguments != null) && (arguments.length != 0)) {
            for (int i = 0; i < arguments.length; i++) {
                sb.append(".").append(arguments[i]);
            }
        }
        return sb.toString();
    }

}

  4 系统sevice 方法:

package ehcache.integration.service;

import java.util.List;

import spring.tx.bean.TxdemoBean;
import ehcache.integration.dao.CacheDao;

/**
 * 类描述:  服务层
 * @author shiro
 * @version 1.0  CreateDate: 2015-2-2
 *
 * @history:
 * @updateDate            @updatePerson        @declare
 * 
 */
public class CacheService {
    
    private CacheDao cacheDao;
    
    /**
     * 方法描述:
     *
     */
    public List<TxdemoBean> getList(){
        List<TxdemoBean> rows = cacheDao.selectList();
        return rows;
    }

    /**
     * @return the cacheDao
     */
    public CacheDao getCacheDao() {
        return cacheDao;
    }

    /**
     * @param cacheDao the cacheDao to set
     */
    public void setCacheDao(CacheDao cacheDao) {
        this.cacheDao = cacheDao;
    }

}

  5 调用入口:

package ehcache.integration;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import spring.tx.bean.TxdemoBean;
import ehcache.integration.service.CacheService;

/** 
 * 类描述:  ehcache 集成spring
 * @author shiro
 * @version 1.0  CreateDate: 2015-4-20
 *
 * @updateDate            
 * @updatePerson        
 * @declare 
 */
public class Acce {

    public static void main(String[] args) {
        ApplicationContext context = new FileSystemXmlApplicationContext(
                "WebContent/resource/applicationContext-ehcache.xml");
        CacheService cacheService = (CacheService) context.getBean("cacheService");
//                CacheManager cacheManager = (CacheManager)context.getBean("cacheManager");
//
//                Cache levelOneCache = cacheManager.getCache("SYSCACHE");

        for (int i = 0; i < 5; i++) {
            List<TxdemoBean> rows = cacheService.getList();
            for (TxdemoBean txdemoBean : rows) {
                System.out.println(txdemoBean.toString());
            }
        }

    }
}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。