刨根问底--技术--encache详解

    上文把encache的基本代码展示了,但是有个疑问:没有设置缓存文件ehcache.xml,他是怎么设置进去的啊?并且读到里面的数据呢?

    下面详细解释:

    1、TestEnCache中mian函数中,获得缓存数据

 String cacheName="cacheA";
 String key="key";
 String value="oschina";
 //set(cacheName, key, value);
 String gValue = (String)CacheManager.get(cacheName, key);//A

     2、CacheManager中get(String name, Serializable key)代码:

/**
	 * 获取缓存中的数据
	 * @param name 缓存名
	 * @param key  
	 * @return
	 */
	public final static Object get(String name, Serializable key){
		if(name!=null && key != null)
			return _getCache(name).get(key);
		return null;
	}
注释:首先判断name和key是否为空,如果不为空,获得name相应的缓存,并且从缓存中获取key对应的值


    3、先看看_getCache(String cache_name)的源码:

private static CacheProvider provider;
private final static Cache _getCache(String cache_name) {
		if(provider == null){
			provider = new EhCacheProvider();
			provider.start();
		}
		return provider.buildCache(cache_name);
	}

注释:CacheManager中定义了一个静态变量provider,首先判断provider是否为null,如果为空就new EhCacheProvider ,并且调用start()方法。

    3.1有必要先看看start()方法:


public void start() throws CacheException {
		if (manager != null) {
            log.warn("Attempt to restart an already started EhCacheProvider. Use sessionFactory.close() " +
                    " between repeated calls to buildSessionFactory. Using previously created EhCacheProvider." +
                    " If this behaviour is required, consider using net.sf.ehcache.hibernate.SingletonEhCacheProvider.");
            return;
        }
        manager = new CacheManager();
        _cacheManager = new Hashtable<String, EhCache>();
	}
注释:manager是net.sf.ehcache.CacheManager类型


_cacheManager是Hashtable<String, EhCache>()类型,key是缓存的name,value是EhCache对象。

    4、再回到_getCache(String cache_name)中最后一行buildCache(String name)代码:


 public EhCache buildCache(String name) throws CacheException {
    	EhCache ehcache = _cacheManager.get(name);
    	if(ehcache != null)
    		return ehcache ;
	    try {
            net.sf.ehcache.Cache cache = manager.getCache(name);
            if (cache == null) {
                log.warn("Could not find configuration [" + name + "]; using defaults.");
                manager.addCache(name);
                cache = manager.getCache(name);
                log.debug("started EHCache region: " + name);                
            }
            synchronized(_cacheManager){
	            ehcache = new EhCache(cache);
	            _cacheManager.put(name, ehcache);
	            return ehcache ;
            }
	    }
        catch (net.sf.ehcache.CacheException e) {
            throw new CacheException(e);
        }
    }
注释:(1)首先会查看_cacheManager中是是否保存了和name相对应的EhCache,如果不为空,直接返回


(2)manager.getCache(name)获得net.sf.ehcache.Cache对象,manager.getCache(name)源码:


 protected final Map caches = new ConcurrentHashMap(); 
public Cache getCache(String name) throws IllegalStateException, ClassCastException {
        checkStatus();
        return (Cache) caches.get(name);
    }
这里也是在map中获取和name相对应的Cache,但是没有看到添加啊?怎么搞进来的值呢?后面马上会说到。


(3)new EhCache(cache)创建ehcache对象

(4)把ehcache保存到_cacheManager里面

    5、上面中manager.getCache(name)获得net.sf.ehcache.Cache对象不是null,这是为什么呢?到现在为止没有看到添加map中值啊?在前面执行new CacheManager(),恩,看看CacheManager构造函数吧。


public CacheManager() throws CacheException {
        //default config will be done
        status = Status.STATUS_UNINITIALISED;
        init(null, null, null, null);
    }

    /**
     * initialises the CacheManager
     */
    protected void init(Configuration configuration, String configurationFileName, URL configurationURL,
                        InputStream configurationInputStream) {
        Configuration localConfiguration = configuration;
        if (configuration == null) {
            localConfiguration = parseConfiguration(configurationFileName, configurationURL, configurationInputStream);
        } else {
            localConfiguration.setSource("Programmatically configured.");
        }

        if (localConfiguration.getName() != null) {
            this.name = localConfiguration.getName();
        }
        
        this.terracottaConfigConfiguration = localConfiguration.getTerracottaConfiguration();

        Map<String, CacheConfiguration> cacheConfigs = localConfiguration.getCacheConfigurations();
        for (CacheConfiguration config : cacheConfigs.values()) {
            if (config.isTerracottaClustered()) {
                terracottaStoreFactory = TerracottaStoreHelper.newStoreFactory(
                        cacheConfigs, localConfiguration
                                .getTerracottaConfiguration());
                break;
            }
        }
        
        /*
         * May not have any CacheConfigurations yet, so check the default configuration.
         */
        if (terracottaStoreFactory == null) {
            if (localConfiguration.getDefaultCacheConfiguration().isTerracottaClustered()) {
                terracottaStoreFactory = TerracottaStoreHelper.newStoreFactory(cacheConfigs, localConfiguration
                        .getTerracottaConfiguration());
            }
        }
        
        ConfigurationHelper configurationHelper = new ConfigurationHelper(this, localConfiguration);
        configure(configurationHelper);
        status = Status.STATUS_ALIVE;

        for (CacheManagerPeerProvider cacheManagerPeerProvider : cacheManagerPeerProviders.values()) {
            cacheManagerPeerProvider.init();
        }

        cacheManagerEventListenerRegistry.init();
        addShutdownHookIfRequired();

        cacheManagerTimer = new FailSafeTimer(getName());
        checkForUpdateIfNeeded(localConfiguration.getUpdateCheck());
        
        terracottaStoreFactoryCreated.set(terracottaStoreFactory != null);

        //do this last
        addConfiguredCaches(configurationHelper);

        initializeMBeanRegistrationProvider(localConfiguration);
    }
注释:(1)构造函数中知识简单的调用了一下init(null, null, null, null)方法


(2)configuration传值为空,会执行代码localConfiguration = parseConfiguration(configurationFileName, configurationURL, configurationInputStream),看看代码:

private synchronized Configuration parseConfiguration(String configurationFileName, URL configurationURL,
                                                          InputStream configurationInputStream) throws CacheException {
        reinitialisationCheck();
        Configuration configuration;
        String configurationSource;
        if (configurationFileName != null) {

                LOG.debug("Configuring CacheManager from {}", configurationFileName);
            configuration = ConfigurationFactory.parseConfiguration(new File(configurationFileName));
            configurationSource = "file located at " + configurationFileName;
        } else if (configurationURL != null) {
            configuration = ConfigurationFactory.parseConfiguration(configurationURL);
            configurationSource = "URL of " + configurationURL;
        } else if (configurationInputStream != null) {
            configuration = ConfigurationFactory.parseConfiguration(configurationInputStream);
            configurationSource = "InputStream " + configurationInputStream;
        } else {

                LOG.debug("Configuring ehcache from classpath.");
            configuration = ConfigurationFactory.parseConfiguration();
            configurationSource = "classpath";
        }
        configuration.setSource(configurationSource);
        return configuration;

    }
configurationFileName,configurationURL,configurationInputStream全部传值为空,所以会执行代码: configuration = ConfigurationFactory.parseConfiguration(),没办法看看他到底干嘛了吧:
 public static Configuration parseConfiguration() throws CacheException {
        ClassLoader standardClassloader = ClassLoaderUtil.getStandardClassLoader();
        URL url = null;
        if (standardClassloader != null) {
            url = standardClassloader.getResource(DEFAULT_CLASSPATH_CONFIGURATION_FILE);
        }
        if (url == null) {
            url = ConfigurationFactory.class.getResource(DEFAULT_CLASSPATH_CONFIGURATION_FILE);
        }
        if (url != null) {
            LOG.debug("Configuring ehcache from ehcache.xml found in the classpath: " + url);
        } else {
            url = ConfigurationFactory.class.getResource(FAILSAFE_CLASSPATH_CONFIGURATION_FILE);

            LOG.warn("No configuration found. Configuring ehcache from ehcache-failsafe.xml "
                    + " found in the classpath: {}", url);

        }
        return parseConfiguration(url);
    }
DEFAULT_CLASSPATH_CONFIGURATION_FILE是/ehcache.xml,这里主要的任务就是加载 ehcache.xml文件,哈哈哈,这就是加载 ehcache.xml文件了。

回到init方法中,然后会把文件中数据添加到configurationHelper,然后addConfiguredCaches(configurationHelper)会把里面的缓存添加到ehcaches中,

private void addConfiguredCaches(ConfigurationHelper configurationHelper) {
        Set unitialisedCaches = configurationHelper.createCaches();
        for (Iterator iterator = unitialisedCaches.iterator(); iterator.hasNext();) {
            Ehcache unitialisedCache = (Ehcache) iterator.next();
            addCacheNoCheck(unitialisedCache);
        }
    }

private void addCacheNoCheck(Ehcache cache) throws IllegalStateException,
            ObjectExistsException, CacheException {
        if (ehcaches.get(cache.getName()) != null) {
            throw new ObjectExistsException("Cache " + cache.getName() + " already exists");
        }
        cache.setCacheManager(this);
        cache.setDiskStorePath(diskStorePath);
        cache.initialise();
        try {
            cache.bootstrap();
        } catch (CacheException e) {
            LOG.warn("Cache " + cache.getName() + "requested bootstrap but a CacheException occured. " + e.getMessage(), e);
        }
        ehcaches.put(cache.getName(), cache);
        if (cache instanceof Cache) {
            caches.put(cache.getName(), cache);
        }

        //Don't notify initial config. The init method of each listener should take care of this.
        if (status.equals(Status.STATUS_ALIVE)) {
            cacheManagerEventListenerRegistry.notifyCacheAdded(cache.getName());
        }
    }
恩,到这里就结束了。

这篇文章的重点:

(1)在哪加载ehcache.xml文件

(2)在哪把缓存相应的信息添加到ehcaches中


    

你可能感兴趣的:(刨根问底--技术--encache详解)