首先,以下代码是在一位大神代码的基础上进行了稍加修改
一、自定义缓存框架
所用到的技术:cglib动态代理(MethodInterceptor),自定义注解,BeanPostProcessor接口的使用,
实现org.springframework.cglib.proxy.MethodInterceptor接口,可以做到环绕增强
实现org.springframework.beans.factory.config.BeanPostProcessor接口,可以在Spring上下文初始化Bean前后,增加自己的业务逻辑
二、使用的类如下
CacheProxy.java => 定义哪里类的方法进行缓存(类级别注解)
package com.wilbur.cache;
@Target(ElementType.TYPE)
@Retention(Retention.RUNTIME)
public @interface CacheProxy{
}
Cache.java => 定义哪些方法进行缓存(方法级别注解)
package com.wilbur.cache;
@Target(ElementType.METHOD)
@Retention(Retention.RUNTIME)
public @interface Cache{
//时间刻度,天、时、分...
int timeScale();
//时间间隔
int timeInterval();
}
CacheWrapper.java => 缓存包装类,定义过期刷新,及缓存值
package com.wilbur.cache;
public class CacheWrapper<T>{
//缓存对象
T cacheValue;
//定时器
Calendar timer;
//定时器域(时分秒..)
int field;
//定时器间隔
int amount;
public CacheWrapper(Cache cache){
this(cache.timeScale(),cache.timeInterval());
}
public CacheWrappe(int field,int amount){
this.field = field;
this.amount = amount;
resetTimer();
}
public void resetTimer(){
timer = Calendar.getInstance();
timer.add(field,amount);
}
public boolean isTimeOut(){
return Calendar.getInstance().after(timer);
}
public T getCacheValue(){
return cacheValue;
}
public void setCacheValue(){
this.cacheValue = cacheValue;
}
}
CacheMethodInterceptor.java => 代理类,主要的业务逻辑
package com.wilbur.cache;
public class CacheMethodInterceptor implements MethodInterceptor{
//代理对象
private Object target;
//缓存
private Map<String,CacheWrapper<Object>> cacheWrapper = new HashMap<String,CacheWrapper<Object>>();
public CacheMethodInterceptor (){
}
public CacheMethodInterceptor (Object target){
this.target = target;
}
@override
public Object intercept(Object arg0,Method method,Object[] args,MethodProxy proxy) thows Throwable{
Object result = null;
CacheWrapper wrapper = null;
Cache cache = method.getAnnotation(Cache.class);
if(!(cache == null && cache.timeInterval() <= 0)){
if(cacheWrapper.containsKey(method.toString())){
wrapper = cacheWrapper.getKey(method.toString());
}else{
wrapper = new CacheWrapper(cache);
result = method.invoke(target,args);
wrapper.setCacheValue(result );
cacheWrapper.put(method.toString(),wrapper);
}
if(wrapper.isTimeOut()){
//缓存过期
synchronized(wrapper){
if(wrapper.isTimeOut()){
wrapper.resetTimer();
result = method.invoke(target,args);
wrapper.setCacheValue(result);
}else{
result = wrapper.getCacheValue();
}
}
}else{
result = wrapper.getCacheValue();
}
}else{
//如果不需求缓存,即没有Cache注解
result = method.invoke(target,args);
}
return result;
}
}
CachePostBeanProcessor.java => Spring容器初始化时,为缓存的类进行代理类
package com.wilbur.cache;
public class CachePostBeanProcessor implements BeanPostProcessor{
@override
public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException{
if(bean.getClass().isAnnotationPresent(CacheProxy.class)){
//如果是代理的类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(bean.getClass());
enhancer.setCallback(new CachceMethodInterceptor(bean));
return enhancer.create();
}else{
return bean;
}
}
public Object postProcessBeforeInitialization(Object bean,String beanNames) throws BeansException{
return bean;
}
}
三、测试
package com.wilbur.domain;
public User{
private String name;
private int age;
public User(){
}
public User(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return "User: name = " + name + " age = " + age;
}
}
package com.wilbur.repository;
public class UserRepository{
public UserRepository(){
}
public User getUser(){
return new User("wilbur",10);
}
}
package com.wilbur.service;
public interface IUserService{
public User getUser();
}
package com.wilbur.service.impl;
@CacheProxy
public class UserServiceImpl implements IUserService{
//10秒刷新一次
@Cache(timeScale = Calendar.SENCOD,timeInterval = 10)
public User getUser(){
System.out.println("Time Out");
return new UserRepository().getUser();
}
}
package test;
public class Test{
public static void main(String[] args){
ApplicationContext context = ClassPathXmlApplicationContext("beans.xml");
IUserService serivce = (IUserService)context.getBean("IUserService");
while(true){
System.out.println(serivce.getUser());
try{
Thread.sleep(1000);
}catch(EXception e){
}
}
}
}
beans.xml
<bean class="com.wilbur.cache.CachePostBeanProcessor"/>
<bean id="IUserService" class="com.wilbur.service.impl.UserServiceImpl"/>
四、结果
我们可以看到Time Out 10s出现一次,说明10s 会重新刷新缓存