基于cglib动态代理的缓存框架

首先,以下代码是在一位大神代码的基础上进行了稍加修改

一、自定义缓存框架
所用到的技术: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 会重新刷新缓存

转载于:https://my.oschina.net/u/204498/blog/163534

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值