Mybatis学习[1] Mybatis中的设计模式之单例模式

562 阅读2分钟

1.单例模式详解

👉 看这篇文章就够了,详细的一批,各种实现单例模式的方式以及优缺点都列举出来了,令人幸福XD

2.Mybatis中的单例模式

Mybaits中的org.apache.ibatis.io.VFS使用到了单例模式。

VFS就是Virtual File System的意思,mybatis通过VFS来查找指定路径下的资源。查看VFS以及它的实现类,不难发现,VFS的角色就是对更“底层”的查找指定资源的方法的封装,将复杂的“底层”操作封装到易于使用的高层模块中,方便使用者使用。

有点扯远了,下面我们来看看VFS是如何实现单例模式的,下面是VFS的源码,省略去了与单例模式无关的部分:

/**
 * Provides a very simple API for accessing resources within an application server.
 *
 * @author Ben Gunter
 */
public abstract class VFS {
  private static final Log log = LogFactory.getLog(VFS.class);

  /** Singleton instance holder. */
  private static class VFSHolder {
    static final VFS INSTANCE = createVFS();

    @SuppressWarnings("unchecked")
    static VFS createVFS() {
      // Try the user implementations first, then the built-ins
      List<Class<? extends VFS>> impls = new ArrayList<>();
      impls.addAll(USER_IMPLEMENTATIONS);
      impls.addAll(Arrays.asList((Class<? extends VFS>[]) IMPLEMENTATIONS));

      // Try each implementation class until a valid one is found
      VFS vfs = null;
      for (int i = 0; vfs == null || !vfs.isValid(); i++) {
        Class<? extends VFS> impl = impls.get(i);
        try {
          vfs = impl.getDeclaredConstructor().newInstance();
          if (!vfs.isValid() && log.isDebugEnabled()) {
            log.debug("VFS implementation " + impl.getName()
                + " is not valid in this environment.");
          }
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
          log.error("Failed to instantiate " + impl, e);
          return null;
        }
      }

      if (log.isDebugEnabled()) {
        log.debug("Using VFS adapter " + vfs.getClass().getName());
      }

      return vfs;
    }
  }

  /**
   * Get the singleton {@link VFS} instance. If no {@link VFS} implementation can be found for the current environment,
   * then this method returns null.
   *
   * @return single instance of VFS
   */
  public static VFS getInstance() {
    return VFSHolder.INSTANCE;
  }

}

VFS在自己的内部设置了一个静态内部类,静态内部类中持有一个静态的VFS实例,这个实例通过createVFS()方法创建。

 static final VFS INSTANCE = createVFS();

看了章节 “1.单例模式详解”中对单例模式的详解,我们都知道单例模式是分为“饿汉单例模式”和“懒汉单例模式”,那VFS的这种单例实现方式是属于什么模式呢?下面,我们就仿照VFS的结构来实现一个一样的单例模式,来一探究竟。

public class VFS {

    private VFS() { }

    public static VFS getNone() {
        System.out.println("虚晃一枪~");
        return null;
    }

    public static VFS getInstance() {
        return VFSHolder.SINGLE_INSTANCE;
    }

    private static class VFSHolder {

        private static final VFS SINGLE_INSTANCE = createSingleInstance();

        private static VFS createSingleInstance() {
            System.out.println("创建VFS单例");
            return new VFS();
        }

    }

    public static void main(String[] args) {

        VFS.getNone();

        VFS.getInstance();

        return;

    }

}

执行上述main方法,控制台输出如下:

虚晃一枪~
创建VFS单例

由上述控制台的输出结果我们可以知道,VFS使用的是“懒汉单例模式”,利用了“静态内部类只有被调用的时候才会被加载”的特性来实现,且因为classloader加载类的时候是线程安全的,所以这种方式的懒加载单例实例也是线程安全的。