/* * Copyright 2009-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.mapping; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.CacheException; import org.apache.ibatis.cache.decorators.BlockingCache; import org.apache.ibatis.cache.decorators.LoggingCache; import org.apache.ibatis.cache.decorators.LruCache; import org.apache.ibatis.cache.decorators.ScheduledCache; import org.apache.ibatis.cache.decorators.SerializedCache; import org.apache.ibatis.cache.decorators.SynchronizedCache; import org.apache.ibatis.cache.impl.PerpetualCache; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; /** * @author Clinton Begin */ /** * 缓存构建器,建造者模式 * */ public class CacheBuilder { private String id; private Class<? extends Cache> implementation; private List<Class<? extends Cache>> decorators; private Integer size; private Long clearInterval; private boolean readWrite; private Properties properties; private boolean blocking; public CacheBuilder(String id) { this.id = id; this.decorators = new ArrayList<Class<? extends Cache>>(); } public CacheBuilder implementation(Class<? extends Cache> implementation) { this.implementation = implementation; return this; } public CacheBuilder addDecorator(Class<? extends Cache> decorator) { if (decorator != null) { this.decorators.add(decorator); } return this; } public CacheBuilder size(Integer size) { this.size = size; return this; } public CacheBuilder clearInterval(Long clearInterval) { this.clearInterval = clearInterval; return this; } public CacheBuilder readWrite(boolean readWrite) { this.readWrite = readWrite; return this; } public CacheBuilder blocking(boolean blocking) { this.blocking = blocking; return this; } public CacheBuilder properties(Properties properties) { this.properties = properties; return this; } public Cache build() { setDefaultImplementations(); //先new一个base的cache(PerpetualCache) Cache cache = newBaseCacheInstance(implementation, id); //设额外属性 setCacheProperties(cache); // issue #352, do not apply decorators to custom caches if (PerpetualCache.class.equals(cache.getClass())) { for (Class<? extends Cache> decorator : decorators) { //装饰者模式一个个包装cache cache = newCacheDecoratorInstance(decorator, cache); //又要来一遍设额外属性 setCacheProperties(cache); } //最后附加上标准的装饰者 cache = setStandardDecorators(cache); } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) { //如果是custom缓存,且不是日志,要加日志 cache = new LoggingCache(cache); } return cache; } private void setDefaultImplementations() { //又是一重保险,如果为null则设默认值,和XMLMapperBuilder.cacheElement以及MapperBuilderAssistant.useNewCache逻辑重复了 if (implementation == null) { implementation = PerpetualCache.class; if (decorators.isEmpty()) { decorators.add(LruCache.class); } } } //最后附加上标准的装饰者 private Cache setStandardDecorators(Cache cache) { try { MetaObject metaCache = SystemMetaObject.forObject(cache); if (size != null && metaCache.hasSetter("size")) { metaCache.setValue("size", size); } if (clearInterval != null) { //刷新缓存间隔,怎么刷新呢,用ScheduledCache来刷,还是装饰者模式,漂亮! cache = new ScheduledCache(cache); ((ScheduledCache) cache).setClearInterval(clearInterval); } if (readWrite) { //如果readOnly=false,可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。 cache = new SerializedCache(cache); } //日志缓存 cache = new LoggingCache(cache); //同步缓存, 3.2.6以后这个类已经没用了,考虑到Hazelcast, EhCache已经有锁机制了,所以这个锁就画蛇添足了。 cache = new SynchronizedCache(cache); if (blocking) { cache = new BlockingCache(cache); } return cache; } catch (Exception e) { throw new CacheException("Error building standard cache decorators. Cause: " + e, e); } } private void setCacheProperties(Cache cache) { if (properties != null) { MetaObject metaCache = SystemMetaObject.forObject(cache); //用反射设置额外的property属性 for (Map.Entry<Object, Object> entry : properties.entrySet()) { String name = (String) entry.getKey(); String value = (String) entry.getValue(); if (metaCache.hasSetter(name)) { Class<?> type = metaCache.getSetterType(name); //下面就是各种基本类型的判断了,味同嚼蜡但是又不得不写 if (String.class == type) { metaCache.setValue(name, value); } else if (int.class == type || Integer.class == type) { metaCache.setValue(name, Integer.valueOf(value)); } else if (long.class == type || Long.class == type) { metaCache.setValue(name, Long.valueOf(value)); } else if (short.class == type || Short.class == type) { metaCache.setValue(name, Short.valueOf(value)); } else if (byte.class == type || Byte.class == type) { metaCache.setValue(name, Byte.valueOf(value)); } else if (float.class == type || Float.class == type) { metaCache.setValue(name, Float.valueOf(value)); } else if (boolean.class == type || Boolean.class == type) { metaCache.setValue(name, Boolean.valueOf(value)); } else if (double.class == type || Double.class == type) { metaCache.setValue(name, Double.valueOf(value)); } else { throw new CacheException("Unsupported property type for cache: '" + name + "' of type " + type); } } } } } private Cache newBaseCacheInstance(Class<? extends Cache> cacheClass, String id) { Constructor<? extends Cache> cacheConstructor = getBaseCacheConstructor(cacheClass); try { return cacheConstructor.newInstance(id); } catch (Exception e) { throw new CacheException("Could not instantiate cache implementation (" + cacheClass + "). Cause: " + e, e); } } private Constructor<? extends Cache> getBaseCacheConstructor(Class<? extends Cache> cacheClass) { try { return cacheClass.getConstructor(String.class); } catch (Exception e) { throw new CacheException("Invalid base cache implementation (" + cacheClass + "). " + "Base cache implementations must have a constructor that takes a String id as a parameter. Cause: " + e, e); } } private Cache newCacheDecoratorInstance(Class<? extends Cache> cacheClass, Cache base) { Constructor<? extends Cache> cacheConstructor = getCacheDecoratorConstructor(cacheClass); try { return cacheConstructor.newInstance(base); } catch (Exception e) { throw new CacheException("Could not instantiate cache decorator (" + cacheClass + "). Cause: " + e, e); } } private Constructor<? extends Cache> getCacheDecoratorConstructor(Class<? extends Cache> cacheClass) { try { return cacheClass.getConstructor(Cache.class); } catch (Exception e) { throw new CacheException("Invalid cache decorator (" + cacheClass + "). " + "Cache decorators must have a constructor that takes a Cache instance as a parameter. Cause: " + e, e); } } }