Need spring jar and ehcache-2.41.jar and so on.
1.Spring applicationContext.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"
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-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/aop http://www.springframework.org/schema/aop/spring-aop- 2.5.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:applicationContext-Freedom.properties</value>
</list>
</property>
</bean>
<!-- Init base package, for com.tian.rates -->
<context:component-scan base- package="com.tian.rates.dao,com.tian.rates.services,com.tian.rates.cache,com.tian.rates.action"/>
<!-- For asperctj, we use it for @around and @after for cache interceptor -->
<aop:aspectj-autoproxy />
<!-- DataSource config, use dbcp database connect pool --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- Connection Info --> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- For Hibernate --> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> </props> </property> <property name="mappingResources"> <list> <value>ABC/Abc.hbm.xml</value> </list> </property> </bean>
<bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation"> <value>classpath:ehcache-Freedom.xml</value> </property> </bean> <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager"> <ref local="defaultCacheManager"/> </property> <property name="cacheName"> <value>DEFAULT_CACHE</value> </property> </bean>
</bean>
2. ehcache-Freedom.xml
<ehcache>
<diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> <cache name="DEFAULT_CACHE" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300000" timeToLiveSeconds="600000" overflowToDisk="true" /> </ehcache>
3. Cache interceptor and after advice with annotation.
a) CacheAfterAdviceAspect.java and b)CacheInterceptorAspect.java
package com.tian.rates.cache; import java.util.List; import net.sf.ehcache.Cache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component;
@Aspect
@Component
public class CacheInterceptorAspect {
private static final Log logger = LogFactory
.getLog(CacheInterceptorAspect.class);
@Autowired @Qualifier("ehCache") private Cache ehCache;
@SuppressWarnings("unchecked") @Around("execution(public * com.tian.rates.dao..*find*(..)) || execution(public * com.tian.rates.dao..*get*(..))") public Object invoke(ProceedingJoinPoint pjp) throws Throwable { System.out .println("---------- Into cache Intercepter method--------------------"); String targetName = pjp.getTarget().getClass().getName(); String methodName = pjp.getSignature().getName(); Object[] arguments = pjp.getArgs(); Object result; logger.debug("Find object from cache is " + ehCache.getName()); String cacheKey = getCacheKey(targetName, methodName, arguments); Element element = ehCache.get(cacheKey); if (element == null) { logger .debug("Hold up method , Get method result and create cache........!"); result = pjp.proceed(); Map map = new HashMap(); map.put("invocation", pjp); map.put("result", (Serializable) result); element = new Element(cacheKey, map); ehCache.put(element); return (Serializable) result; } else { Map map = (Map) element.getValue(); return map.get("result"); } } /** */ 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(); } }
b)
package com.tian.rates.cache; import java.util.List; import net.sf.ehcache.Cache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component;
@Aspect @Component public class CacheAfterAdviceAspect { private static final Log logger = LogFactory .getLog(CacheAfterAdviceAspect.class); @Autowired @Qualifier("ehCache") private Cache ehCache; @SuppressWarnings("unchecked") @Around("execution(public * com.tian.rates.dao..*create*(..)) ||" + "execution(public * com.tian.rates.dao..*save*(..)) ||" + "execution(public * com.tian.rates.dao..*update*(..))||" + "execution(public * com.tian.rates.dao..*delete*(..))") public Object afterReturning(ProceedingJoinPoint pjp) throws Throwable { // before advice Object object = pjp.proceed(); // After advice, below is after advice process System.out .println("---------- Into cache After Advice method--------------------"); String targetName = pjp.getTarget().getClass().getName(); List<String> list = ehCache.getKeys(); for (String cacheKey : list) { if (cacheKey.startsWith(targetName)) { ehCache.remove(cacheKey); logger.debug("delete from cache " + cacheKey); } } // return message return object; } }
4.web.xml
<!-- Spring Config Start --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
5. Struts.xml
<package name="rates" extends="struts-default" namespace="/test"> <action name="TestSpring" class="com.tian.rates.action.TestSpringAction"> <result name="env">/env.jsp</result> </action> </package>
6. TestSpringAction.java
package com.tian.rates.action;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import com.tian.rates.services.TestService;
import com.opensymphony.xwork2.ActionSupport;
@Controller public class TestSpringAction extends ActionSupport{ /** * */ private static final long serialVersionUID = -7237842340724756585L; @Autowired @Qualifier("testService") private TestService testService; @Override public String execute() throws Exception { String result = testService.getStr(); System.out.println("Action return:"+result); return "env"; } public void remove(){ String result = testService.deleteData(10l); System.out.println("Action return, delete result:"+result); } public void save(){ String result = testService.saveData(20l); System.out.println("Action return, Save result:"+result); } public void print(){ testService.PrintTest(); } public static void main(String[] args) throws Exception { TestSpringAction service = new TestSpringAction(); ApplicationContext ac = new ClassPathXmlApplicationContext( "applicationContext*.xml"); service = (TestSpringAction) ac.getBean("testSpringAction"); service.execute(); } }
6. tetDao and testService is very sample, so don't paste here.
This function is use the @Aspect annotation'S @Around and @after to interceptor the dao layer's method(Such as *find* and *get* for cache), and put them into ehcache, and if have the save, create, update and delete operation remove the object from cache. And all ioc and aop use the annotation.