oscache源代码阅读(一) -- 将pojo放入缓存

其实之前我完全没有接触过oscache,今天突发奇想,准备看看缓存是怎么实现的,google了一下,决定看看oscache的源码,简单的写了个TestCase:

    @Test
    
public   void  testPojoCache()  throws  Exception  {
        TestPojo pojo 
=   new  TestPojo( " 0001 " );
        pojo.setField1(
100 );
        pojo.setField2(
" 100 " );

        Properties prop 
=   new  Properties();
        InputStream is 
=   this .getClass().getResourceAsStream( " oscache.properties " );
        prop.load(is);

        is.close();

        GeneralCacheAdministrator cacheAdmin 
=   new  GeneralCacheAdministrator(prop);

        cacheAdmin.putInCache(pojo.getId(), pojo);

        TestPojo cachedObj 
=  (TestPojo) cacheAdmin.getFromCache( " 0001 " );

        assertEquals(
100 , cachedObj.getField1());
        assertEquals(
" 100 " , cachedObj.getField2());

    }

 

所以我对这个产品的熟悉程度基本为0,各位大虾看了后发现误人子弟请用砖轻拍。

简单了看了下oscache的介绍,发现它支持三种缓存方式:JSP Caching、Request Caching、General-Purpose Cache,今天的文章就是针对最后一种General-Purpose Cache的,在oscache中对应的入口是GeneralCacheAdministrator,就从这里开始吧:

     public  GeneralCacheAdministrator(Properties p)  {
        
super (p);
        log.info(
" Constructed GeneralCacheAdministrator() " );
        createCache();
    }


    
//  这个是super(p)调用的构造函数
     protected  AbstractCacheAdministrator(Properties p)  {
        loadProps(p);
        initCacheParameters();

        
if  (log.isDebugEnabled())  {
            log.debug(
" Constructed AbstractCacheAdministrator() " );
        }

    }


    
//  初始化参数
     private   void  initCacheParameters()  {
        algorithmClass 
=  getProperty(CACHE_ALGORITHM_KEY);

        blocking 
=   " true " .equalsIgnoreCase(getProperty(CACHE_BLOCKING_KEY));

        String cacheMemoryStr 
=  getProperty(CACHE_MEMORY_KEY);

        
if  ((cacheMemoryStr  !=   null &&  cacheMemoryStr.equalsIgnoreCase( " false " ))  {
            memoryCaching 
=   false ;
        }


        unlimitedDiskCache 
=  Boolean.valueOf(config.getProperty(CACHE_DISK_UNLIMITED_KEY)).booleanValue();
        overflowPersistence 
=  Boolean.valueOf(config.getProperty(CACHE_PERSISTENCE_OVERFLOW_KEY))
                .booleanValue();

        String cacheSize 
=  getProperty(CACHE_CAPACITY_KEY);

        
try   {
            
if  ((cacheSize  !=   null &&  (cacheSize.length()  >   0 ))  {
                cacheCapacity 
=  Integer.parseInt(cacheSize);
            }

        }
  catch  (NumberFormatException e)  {
            log.error(
" The value supplied for the cache capacity, ' "   +  cacheSize
                    
+   " ', is not a valid number. The cache capacity setting is being ignored. " );
        }

    }


    
//  创建缓存实例
     private   void  createCache()  {
        log.info(
" Creating new cache " );

        
//  这里构建缓存时用到的参数都是在父类里的#initCacheParameters()中初始化的
        applicationCache  =   new  Cache(isMemoryCaching(), isUnlimitedDiskCache(), isOverflowPersistence(),
                isBlocking(), algorithmClass, cacheCapacity);

        configureStandardListeners(applicationCache);
    }


    
//  Cache的构造函数
     public  Cache( boolean  useMemoryCaching,  boolean  unlimitedDiskCache,  boolean  overflowPersistence,
            
boolean  blocking, String algorithmClass,  int  capacity)  {
        
//  这里说明还是支持自定义的缓存策略的
         if  (((algorithmClass  !=   null &&  (algorithmClass.length()  >   0 ))  &&  (capacity  >   0 ))  {
            
try   {
                cacheMap 
=  (AbstractConcurrentReadCache) Class.forName(algorithmClass).newInstance();
                cacheMap.setMaxEntries(capacity);
            }
  catch  (Exception e)  {
                log.error(
" Invalid class name for cache algorithm class.  "   +  e.toString());
            }

        }


        
if  (cacheMap  ==   null {
            
//  选择一个默认的策略
             if  (capacity  >   0 { //  如果有缓存数目的限制,使用LRU
                cacheMap  =   new  LRUCache(capacity);
            }
  else   { //  否则使用Unlimited
                cacheMap  =   new  UnlimitedCache();
            }

        }


        cacheMap.setUnlimitedDiskCache(unlimitedDiskCache);
        cacheMap.setOverflowPersistence(overflowPersistence);
        cacheMap.setMemoryCaching(useMemoryCaching);

        
this .blocking  =  blocking;
    }


    
//  配置事件的listener
     protected  Cache configureStandardListeners(Cache cache)  {
        
if  (config.getProperty(PERSISTENCE_CLASS_KEY)  !=   null {
            cache 
=  setPersistenceListener(cache);
        }


        
if  (config.getProperty(CACHE_ENTRY_EVENT_LISTENERS_KEY)  !=   null {
            
//  Grab all the specified listeners and add them to the cache's
            
//  listener list. Note that listeners that implement more than
            
//  one of the event interfaces will be added multiple times.
            CacheEventListener[] listeners  =  getCacheEventListeners();

            
for  ( int  i  =   0 ; i  <  listeners.length; i ++ {
                
//  Pass through the configuration to those listeners that
                
//  require it
                 if  (listeners[i]  instanceof  LifecycleAware)  {
                    
try   {
                        ((LifecycleAware) listeners[i]).initialize(cache, config);
                    }
  catch  (InitializationException e)  {
                        log.error(
" Could not initialize listener ' "   +  listeners[i].getClass().getName()
                                
+   " '. Listener ignored. " , e);

                        
continue ;
                    }

                }


                
if  (listeners[i]  instanceof  CacheEntryEventListener)  {
                    cache.addCacheEventListener(listeners[i]);
                }
  else   if  (listeners[i]  instanceof  CacheMapAccessEventListener)  {
                    cache.addCacheEventListener(listeners[i]);
                }

            }

        }


        
return  cache;
    }

 

这里对缓存#initCacheParameters()和#configureStandardListeners()里的参数大致了解下,代码里有注释良好的JavaDoc,很容易看懂。

1. cache.algorithm 缓存的策略,具体就是用哪种Map来实现缓存,默认有FIFO,LRU,Unlimited三种,也支持自定义的缓存类型的;
2. cache.blocking 是否等待新数据放入缓存,这个感觉应该是在并发读取数据的时候如果数据在其他线程正处于写入的状态这个线程会wait()直到写入线程完成写入后notifyAll();
3. cache.memory 这个是是否使用内存缓存,这个多数情况下都应该是内存的吧;
4. cache.unlimited.disk 看介绍写的是当对象需要持久化缓存(应该是串行化吧)时,是否使用无限的磁盘空间;
5. cache.persistence.overflow.only 这个说明持久化缓存是不是仅在溢出的方式下开启,字面理解应该是否仅在是memory缓存不足的情况开启持久化缓存;
6. cache.capacity 保存的对象的数目。
7. cache.persistence.class 用于持久化的类名
8. cache.event.listeners 缓存事件监听器,多个listener使用逗号分隔开

初始化大致就这么多,还是看看GeneralCacheAdministrator#putInCache()方法吧,这 里#putInCache()有4个,我挑了一个参数最多的:putInCache(String key, Object content, String[] groups, EntryRefreshPolicy policy)

 

     /** */ /**
     * Puts an object in a cache
     * 
     * 
@param  key The unique key for this cached object
     * 
@param  content The object to store
     * 
@param  groups The groups that this object belongs to
     * 
@param  policy The refresh policy to use
     
*/

    
public   void  putInCache(String key, Object content, String[] groups, EntryRefreshPolicy policy)  {
        
//  直接调用的Cache类的#putInCache
        getCache().putInCache(key, content, groups, policy,  null );
    }


    
//  Cache的#putInCache()方法
     public   void  putInCache(String key, Object content, String[] groups, EntryRefreshPolicy policy,
            String origin) 
{
        
//  首先查找这个key在缓存中是否已经存在,没有就创建一个
        CacheEntry cacheEntry  =   this .getCacheEntry(key, policy, origin);

        
//  判断是否是新创建的缓存
         boolean  isNewEntry  =  cacheEntry.isNew();

        
//  [CACHE-118] If we have an existing entry, create a new CacheEntry so
        
//  we can still access the old one later
        
//  这里如果不是新的缓存也会新建一个CacheEntry,因为老的缓存值在后边也能访问到
         if  ( ! isNewEntry)  {
            cacheEntry 
=   new  CacheEntry(key, policy);
        }


        cacheEntry.setContent(content);
        cacheEntry.setGroups(groups);

        
//  放入缓存
        cacheMap.put(key, cacheEntry);

        
//  Signal to any threads waiting on this update that it's now ready for them in the cache!
        
//  这里会通知其他在等待值的线程结束wait
        completeUpdate(key);

        
//  针对缓存事件的listener发送事件
         if  (listenerList.getListenerCount()  >   0 {
            CacheEntryEvent event 
=   new  CacheEntryEvent( this , cacheEntry, origin);

            
if  (isNewEntry)  {
                dispatchCacheEntryEvent(CacheEntryEventType.ENTRY_ADDED, event);
            }
  else   {
                dispatchCacheEntryEvent(CacheEntryEventType.ENTRY_UPDATED, event);
            }

        }

    }


先简单的看看CacheEntry的构造函数吧,这个最基本:

     public  CacheEntry(String key, EntryRefreshPolicy policy, String[] groups)  {
        
//  CacheEntry中保存了key,所属的分组(用一个HashSet保存分组的名字,有点像Tag)
        
//  还有刷新策略和创建的时间
         this .key  =  key;

        
if  (groups  !=   null {
            
this .groups  =   new  HashSet(groups.length);

            
for  ( int  i  =   0 ; i  <  groups.length; i ++ {
                
this .groups.add(groups[i]);
            }

        }


        
this .policy  =  policy;
        
this .created  =  System.currentTimeMillis();
    }


另外还有#completeUpdate()方法:

     protected   void  completeUpdate(String key)  {
        
//  Entry的更
分享到:
评论

你可能感兴趣的:(多线程,jsp,cache,Google,Access)