我们开始剖析PageHelper的文件结构与类结构。
在昨天的文章中,我们了解了PageHelper中的包com.github.pagehelper
中的几个类。
今天我们来看pagehelper
中几个子包中的类。
我们先来看看pagehelper
的几个子包:
com.github.pagehelper.cache, com.github.pagehelper.dialect, com.github.pagehelper.page, com.github.pagehelper.parser, com.github.pagehelper.util`
cache包
顾名思义,这个包应该和缓存有关。其中包括:接口 Cache<K, V>
, 抽象工厂类CacheFactory
,实现 Cache<K, V>
接口的 SimpleCache<K, V>
, GuavaCache<K, V>
。
接口 Cache<K, V> 中定义了两个基本方法:get, set。 . 抽象工厂类 CacheFactory 中有一个静态方法 createCache,返回值类型为接口 Cache<K, V>。在 createCache 中用到了一个不太常用的Java中的公共方法 Class.forName(full-className)。
SimpleCache<K, V> 中定义了一个无法修改的变量CACHE,一个构造器 SimpleCache(Properties properties, String prefix),以及实现接口 Cache<K, V> 中的get, set方法。
GuavaCache<K, V> 中同样定义了一个无法修改的变量CACHE,一个构造器GuavaCache(Properties properties, String prefix),以及实现接口Cache<K, V>中的get, set方法。
两个缓存实现类中的不同在于SimpleCache中的CACHE类型为:org.apache.ibatis.cache.Cache<K, V>,而GuavaCache中其类型为:com.google.common.cache.Cache<K, V>。
我们先来看一下工厂类CacheFactory中的createCache方法:
/** * 创建 SQL 缓存 * * @param sqlCacheClass * @return */ public static <K, V> Cache<K, V> createCache(String sqlCacheClass, String prefix, Properties properties) { if (StringUtil.isEmpty(sqlCacheClass)) { try { Class.forName("com.google.common.cache.Cache"); return new GuavaCache<K, V>(properties, prefix); } catch (Throwable t) { return new SimpleCache<K, V>(properties, prefix); } } else { try { Class<? extends Cache> clazz = (Class<? extends Cache>) Class.forName(sqlCacheClass); try { Constructor<? extends Cache> constructor = clazz.getConstructor(Properties.class, String.class); return constructor.newInstance(properties, prefix); } catch (Exception e) { return clazz.newInstance(); } } catch (Throwable t) { throw new PageException("Created Sql Cache [" + sqlCacheClass + "] Error", t); } } }
通过是否传入sqlCacheClass
决定两个逻辑。
当sqlCacheClass不指定时,先尝试创建 GuavaCache
,创建失败时再创建 SimpleCache
。创建GuavaCache之前为什要执行下面这行代码呢?
Class.forName("com.google.common.cache.Cache");
Java官方文档对方法 static Class<?> forName(String className)
的解释是:
返回与带有给定字符串名的类或接口相关联的
Class
对象。
如果我们对Java中数据库链接熟悉的话会更清楚这一点。
一般我们连接Mysql时,程序会有这么几行:
Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, username, password);
而 com.mysql.jdbc.Driver
中有这样一段静态代码:
public class Driver extends NonRegisteringDriver implements java.sql.Driver { static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } public Driver() throws SQLException { // Required for Class.forName().newInstance() } }
而类的初始化过程中会执行一遍类的静态语句,包括静态变量的声明、静态代码块等。
那么问题来了,com.google.common.cache.Cache
是什么样的呢?