您的位置:首页 > 编程语言 > PHP开发

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

2013-10-11 16:27 267 查看
首先,以下代码是在一位大神代码的基础上进行了稍加修改

一、自定义缓存框架

所用到的技术: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 会重新刷新缓存
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐