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加载类的时候是线程安全的,所以这种方式的懒加载单例实例也是线程安全的。