若依系统分页工具学习-PageHelper篇十三

这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

在昨天的文章中,我们介绍了PageHelper中的cache包以及简单介绍了包中各个类的属性与方法;还介绍了Java中一种加载类的方式:Class.forName,并且通过查看com.mysql.jdbc.Driver代码,我们知道,可以通过这种方式可以执行类中的静态代码段。

昨天的问题

我们先来看一下昨天最后留的问题:

com.google.common.cache.Cache是什么样的呢?

我们先来看一下com.google.common.cache.Cache的源代码:

package com.google.common.cache;
public abstract interface Cache<K,V> {
  public abstract  V getIfPresent(java.lang.Object arg0);
  // 此处省略其他方法代码
}
复制代码

我们发现com.google.common.cache.Cache实际上是一个接口,并且其中也并没有任务的静态static代码段需要执行,其中的方法也都是抽象abstract修饰的。

反过来我们再去看PageHelper中的那句代码:

Class.forName("com.google.common.cache.Cache");
复制代码

就成了单纯检测执行环境中是否能够加载com.google.common.cache.Cache类。

CacheFactory指定类名的方式

我们来看看CacheFactorycreateCache是如何通过参数sqlCacheClass指定类名生成指定对象的。

当指定sqlCacheClass时,将执行以下代码:

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);
}
复制代码

第一行结合我们之前对Class.forName的解析很好理解,生成指定的类。

第二行:

Constructor<? extends Cache> constructor = clazz.getConstructor(Properties.class, String.class);
复制代码

从字面意思我们判断,首先是通过第一句获得指定类,然后通过getConstructor获取类的构造器。

第三行:

return constructor.newInstance(properties, prefix);
复制代码

通过构造器生成指定类的一个对象,并且通过上面构造器后面的<? Extends Cache>,我们知道,实现的缓存类需要是com.github.pagehelper.cache.Cache接口的一个实现。

当然,在PageHelper中就有两个实现GuavaCache以及SimpleCache

并且通过查看SimpleCache的代码,我们发现其中的构造器通过cacheBuilder一步一步的实现了成员变量CACHE的初始化,一步一步的判断是否设置了配置文件xxx.typeClass.evictionClassxxx..flushInterval.size等等。

GuavaCache同样也是使用cacheBuilder去逐步构造对象的。

这种构造数据的方式曾在《Effective Java》中提到过,非常便利,值得学习!