3.CacheManager(shiro缓存管理)

上一章我们讲了SecurityManager,接下来的章节顺序是根据SecurityManager的依次实现类的依赖组件来讲。

在讲cacheManager前,我们先了解下Cache。
Cache有效的存储临时对象来提升应用的性能。由于Cache不属于安全框架的核心功能,所以shiro本身并没有完全实现Cache机制。Cache接口相当于底层的缓存框架的顶层接口,shiro的一切的缓存操作都与这个Cache顶层接口操作,而底层的实现可以是任何Cache实例(JAche、Ehcache、OSCache、JBossCache..)。

3.CacheManager(shiro缓存管理)_第1张图片

cacheManager维护了Cache实例的生命周期,它和Cache一样,只是shiro的缓存框架的顶层接口,具体底层实现可以是任意的。

3.CacheManager(shiro缓存管理)_第2张图片

1.CacheManager

//CacheManager管理Cache的声明周期
public interface CacheManager {

    //根据指定的名字获取Cache(为什么需要根据名字?因为CacheManager就相当于一个大容器,只管理Cache<K,V>,而这个Cache<K,V>是个小容器,根据键可以取到对应的值。在shiro里面,AuthenticationInfo(用户登陆信息),AuthorizationInfo(授权信息)生成一个Cache,然后根据唯一的名字存入到CacheManager里),如果不存在,则创建个Cache存入到CacheManager里然后返回。
    public <K, V> Cache<K, V> getCache(String name) throws CacheException;
}

2.AbstractCacheManager

//CacheManager的简单的抽象实现,该实现把Cache都交由ConcurrentMap来管理。
public abstract class AbstractCacheManager implements CacheManager, Destroyable {


    private final ConcurrentMap<String, Cache> caches;


    public AbstractCacheManager() {
        this.caches = new ConcurrentHashMap<String, Cache>();
    }

    //根据名字获取Cache
    public <K, V> Cache<K, V> getCache(String name) throws IllegalArgumentException, CacheException {
        if (!StringUtils.hasText(name)) {
            throw new IllegalArgumentException("Cache name cannot be null or empty.");
        }

        Cache cache;
    //首先根据名字获取从ConcurrentMap里获取cache
        cache = caches.get(name);
        if (cache == null) {
        //如果cache为null的话,则生成个cache存入ConcurrentMap再返回
            cache = createCache(name);
        //putIfAbsent是ConcurrentMap的一个原子性操作,如果已经存在则不添加。
            Cache existing = caches.putIfAbsent(name, cache);
            if (existing != null) {
                cache = existing;
            }
        }

        //noinspection unchecked
        return cache;
    }

    //创建一个Cache,留待子类实现
    protected abstract Cache createCache(String name) throws CacheException;

    //销毁CacheManager
    public void destroy() throws Exception {
        while (!caches.isEmpty()) {
            for (Cache cache : caches.values()) {
        //LifecycleUtils.destroy()里面,会自动判断该cache是否实现了Destroyable,是的话,执行Destroyable的destroy方法。如果是Collection,迭代元素判断是否实现Destroyable,如果实现,则执行Destroyable的destroy方法
                LifecycleUtils.destroy(cache);
            }
            caches.clear();
        }
    }

    public String toString() {
        Collection<Cache> values = caches.values();
        StringBuilder sb = new StringBuilder(getClass().getSimpleName())
                .append(" with ")
                .append(caches.size())
                .append(" cache(s)): [");
        int i = 0;
        for (Cache cache : values) {
            if (i > 0) {
                sb.append(", ");
            }
            sb.append(cache.toString());
            i++;
        }
        sb.append("]");
        return sb.toString();
    }
}

3.MemoryConstrainedCacheManager

//继承AbstractCacheManager
public class MemoryConstrainedCacheManager extends AbstractCacheManager {

    //该类返回一个MapCache(实现Cache)。
    @Override
    protected Cache createCache(String name) {
        //SoftHashMap实现了Map。该实现Map不会引起内存泄露,因为里面引用了弱引用和强引用。默认的强引用是100个。超出了则为弱引用,垃圾回收器可回收这些弱引用,在需要内存的时候。
        return new MapCache<Object, Object>(name, new SoftHashMap<Object, Object>());
    }
}

下面讲的是Ehcache的CacheManager的实现
1.EhCacheManager

//EhCacheManager利用了Ehcache框架来实现所有的缓存功能,可以手动配置net.sf.ehcache.CacheManager和ehcache.xml路径。
public class EhCacheManager implements CacheManager, Initializable, Destroyable {


    private static final Logger log = LoggerFactory.getLogger(EhCacheManager.class);

    //属于ehcache框架的CacheManager,shiro的EhCacheManager仅仅只是代理它实现缓存功能。
    protected net.sf.ehcache.CacheManager manager;

    //表面这个manager是由本实例构造的,而非通过外部注入进来的。需要在销毁的时候执行销毁方法
    private boolean cacheManagerImplicitlyCreated = false;

    // ehcache CacheManager配置文件路径
    private String cacheManagerConfigFile = "classpath:org/apache/shiro/cache/ehcache/ehcache.xml";


    public EhCacheManager() {
    }


    public net.sf.ehcache.CacheManager getCacheManager() {
        return manager;
    }

    //设置ehcache的CacheManager
    public void setCacheManager(net.sf.ehcache.CacheManager manager) {
        this.manager = manager;
    }

    //如果ehcache的CacheManager没有初始化,则获取 ehcache CacheManager的配置文件路径,来初始化ehcache的CacheManager.路径加载方式可以是:classpath:、url:file:
    public String getCacheManagerConfigFile() {
        return this.cacheManagerConfigFile;
    }

    //classpathLocation可以是:classpath:、url:、file:前缀开头的加载方式
    public void setCacheManagerConfigFile(String classpathLocation) {
        this.cacheManagerConfigFile = classpathLocation;
    }

    //使用 ResourceUtils.getInputStreamForPath(configFile)来加载配置文件到InputStream
    protected InputStream getCacheManagerConfigFileInputStream() {
        String configFile = getCacheManagerConfigFile();
        try {
            return ResourceUtils.getInputStreamForPath(configFile);
        } catch (IOException e) {
            throw new ConfigurationException("Unable to obtain input stream for cacheManagerConfigFile [" +
                    configFile + "]", e);
        }
    }

    //根据名字获取Cache
    public final <K, V> Cache<K, V> getCache(String name) throws CacheException {

        if (log.isTraceEnabled()) {
            log.trace("Acquiring EhCache instance named [" + name + "]");
        }

        try {
        //从ehcache框架的CacheManager中根据名字获取ehcache框架的Cache
            net.sf.ehcache.Ehcache cache = ensureCacheManager().getEhcache(name);
            if (cache == null) {
                if (log.isInfoEnabled()) {
                    log.info("Cache with name '{}' does not yet exist. Creating now.", name);
                }
        //根据名字添加cache
                this.manager.addCache(name);
        //重新根据名字获取cache
                cache = manager.getCache(name);

                if (log.isInfoEnabled()) {
                    log.info("Added EhCache named [" + name + "]");
                }
            } else {
                if (log.isInfoEnabled()) {
                    log.info("Using existing EHCache named [" + cache.getName() + "]");
                }
            }
        //shiro的EhCache包装了ehcache框架的Cache,然后返回
            return new EhCache<K, V>(cache);
        } catch (net.sf.ehcache.CacheException e) {
            throw new CacheException(e);
        }
    }

    //下面这个我也不是很理解,希望理解的朋友能告知一二。特别是这句(fail-safe expunges cached objects after 2 minutes, something not desirable for Shiro sessions)。大概意思就是讲,如果没有通过setCacheManager 注入CacheManager,那么该方法就会加载ehcache的配置文件路径初始化一个CacheManager
    /** * Initializes this instance. * <p/> * If a {@link #setCacheManager CacheManager} has been * explicitly set (e.g. via Dependency Injection or programatically) prior to calling this * method, this method does nothing. * <p/> * However, if no {@code CacheManager} has been set, the default Ehcache singleton will be initialized, where * Ehcache will look for an {@code ehcache.xml} file at the root of the classpath. If one is not found, * Ehcache will use its own failsafe configuration file. * <p/> * Because Shiro cannot use the failsafe defaults (fail-safe expunges cached objects after 2 minutes, * something not desirable for Shiro sessions), this class manages an internal default configuration for * this case. * * @throws org.apache.shiro.cache.CacheException * if there are any CacheExceptions thrown by EhCache. * @see net.sf.ehcache.CacheManager#create */
    public final void init() throws CacheException {
        ensureCacheManager();
    }

    private net.sf.ehcache.CacheManager ensureCacheManager() {
        try {
            if (this.manager == null) {
                if (log.isDebugEnabled()) {
                    log.debug("cacheManager property not set. Constructing CacheManager instance... ");
                }
                //because we need to know if we need to destroy the CacheManager instance - using the static call。
                //上面这一句我也不理解。其他几句大概意思就是说,通过CacheManager 的构造方法,得到的实例不是CacheManager里的单例的。我们不知道CacheManager 是否会shutting 它的单例。但是我们通过使用构造EhCacheManager内部的CacheManager,那么EhCacheManager总会shutting EhCacheManager内部的CacheManager。
                //using the CacheManager constructor, the resulting instance is _not_ a VM singleton
                //(as would be the case by calling CacheManager.getInstance(). We do not use the getInstance here
                //because we need to know if we need to destroy the CacheManager instance - using the static call,
                //we don't know which component is responsible for shutting it down. By using a single EhCacheManager,
                //it will always know to shut down the instance if it was responsible for creating it.
                this.manager = new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream());
                if (log.isTraceEnabled()) {
                    log.trace("instantiated Ehcache CacheManager instance.");
                }
                cacheManagerImplicitlyCreated = true;
                if (log.isDebugEnabled()) {
                    log.debug("implicit cacheManager created successfully.");
                }
            }
            return this.manager;
        } catch (Exception e) {
            throw new CacheException(e);
        }
    }

   //如果CacheManager是由EhCacheManager内部构造的,则会执行CacheManager销毁。如果该CacheManager是通过外部组件注入的,那么该外部组件也应该负责销毁CacheManager。
    public void destroy() {
        if (cacheManagerImplicitlyCreated) {
            try {
                net.sf.ehcache.CacheManager cacheMgr = getCacheManager();
                cacheMgr.shutdown();
            } catch (Exception e) {
                if (log.isWarnEnabled()) {
                    log.warn("Unable to cleanly shutdown implicitly created CacheManager instance. " +
                            "Ignoring (shutting down)...");
                }
            }
            cacheManagerImplicitlyCreated = false;
        }
    }
}

你可能感兴趣的:(shiro,缓存,存储,CacheManag)