基於cglib動態代理的緩存框架

首先,如下代碼是在一位大神代碼的基礎上進行了稍加修改java

1、自定義緩存框架
所用到的技術:cglib動態代理(MethodInterceptor),自定義註解,BeanPostProcessor接口的使用,
實現org.springframework.cglib.proxy.MethodInterceptor接口,能夠作到環繞加強
實現org.springframework.beans.factory.config.BeanPostProcessor接口,能夠在Spring上下文初始化Bean先後,增長本身的業務邏輯spring

2、使用的類以下
CacheProxy.java => 定義哪裏類的方法進行緩存(類級別註解)緩存

package com.wilbur.cache;

@Target(ElementType.TYPE)
@Retention(Retention.RUNTIME)
public @interface CacheProxy{
    
}

Cache.java => 定義哪些方法進行緩存(方法級別註解) package com.wilbur.cache;app

@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 => 代理類,主要的業務邏輯dom

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容器初始化時,爲緩存的類進行代理類ide

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;
    }
}

3、測試 package com.wilbur.domain;post

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"/>

4、結果
咱們能夠看到Time Out 10s出現一次,說明10s 會從新刷新緩存測試

相關文章
相關標籤/搜索