spring Modules ehcache 存在缺陷,老是配置不成功,通过@Aspect结合annotation来实现了声明式缓存。
1、在spring的xml配置文件中配置aspectj 如下:
2、创建注释的定义如下:
3、添加ehcache的配置文件
4、写切面类
5、在所有想要缓存的方法上加注标签就能实现缓存了。
1、在spring的xml配置文件中配置aspectj 如下:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<aop:aspectj-autoproxy />
</beans>
2、创建注释的定义如下:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD })
@Documented
public @interface Ehcache {
// 缓存名称,默认为空
String cacheName() default "";
// 增加缓存还是删除缓存,默认为增加缓存
boolean addOrdel() default true;
}
3、添加ehcache的配置文件
<cache name="testCache" maxElementsInMemory="500"
overflowToDisk="true" eternal="true">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicatePuts=false,replicateUpdatesViaCopy=false" />
</cache>
4、写切面类
import java.io.Serializable;
import java.lang.reflect.Method;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class EhcacheAspect {
private static Cache cache;
static {
if (cache == null) {
cache = CacheManager.getInstance().getCache("testCache");
}
}
@Pointcut("@annotation(Ehcache)")
public void simplePointcut() {
}
@AfterReturning(pointcut = "simplePointcut()")
public void simpleAdvice() {
System.out.println("AOP后处理成功");
}
/*
* 试图得到标注方法的Ehcache类 根据Ehcache的属性进行逻辑处理
*/
@Around("simplePointcut()")
public Object aroundLogCalls(ProceedingJoinPoint joinPoint)
throws Throwable {
// 获取连接点的方法签名对象
MethodSignature joinPointObject = (MethodSignature) joinPoint
.getSignature();
// 连接点对象的方法
Method method = joinPointObject.getMethod();
// 连接点方法方法名
String name = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
// 获取连接点所在的目标对象
Object target = joinPoint.getTarget();
// 获取目标方法
method = target.getClass().getMethod(name, parameterTypes);
// 返回@AroundPointCut的注释对象
Ehcache ehcache = method.getAnnotation(Ehcache.class);
String targetName = joinPoint.getTarget().getClass().toString();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Object result;
if ((arguments != null) && (arguments.length != 0)) {
result = joinPoint.proceed(arguments);
} else {
result = joinPoint.proceed();
}
if (ehcache.addOrdel()) {
// 增加缓存
String cacheKey = getCacheKey(targetName, methodName, arguments);
Element element = cache.get(cacheKey);
if (element == null) {
element = new Element(cacheKey, (Serializable) result);
cache.put(element);
}
return element.getValue();
} else {
// 清空缓存
cache.removeAll();
return result;
}
}
/**
* 获得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();
}
}
5、在所有想要缓存的方法上加注标签就能实现缓存了。
//增加缓存
@Ehcache
//删除缓存
@Ehcache(addOrdel=false)