在上一篇中解析了NioEventLoopGroup,其中构造器中需要SelectorProvider,所以本篇就解析SelectorProvider。
解析
SelectorProvider
SelectorProvider就是为了创建DatagramChannel,Pipe,Selector,ServerSocketChannel,SocketChannel,System.inheritedChannel()而服务的,在相应的通道和选择器的open方法中调用系统默认的SelectorProvider相关的open*方法,创建相应的通道和选择器。SelectorProvider的provider方法主要是实例化SelectorProvider。
默认通过sun.nio.ch.DefaultSelectorProvider.create()创建,DefaultSelectorProvider屏蔽了不同的操作系统的不同实现方式。
继承关系
SelectorProvider是个抽象类。
1
| public abstract class SelectorProvider {}
|
成员变量
1 2
| private static final Object lock = new Object(); private static SelectorProvider provider = null;
|
核心方法
从系统配置中获取loadProviderFromProperty()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private static boolean loadProviderFromProperty() { String cn = System.getProperty("java.nio.channels.spi.SelectorProvider"); if (cn == null) return false; try { Class<?> c = Class.forName(cn, true, ClassLoader.getSystemClassLoader()); provider = (SelectorProvider)c.newInstance(); return true; } catch (ClassNotFoundException x) { throw new ServiceConfigurationError(null, x); } catch (IllegalAccessException x) { throw new ServiceConfigurationError(null, x); } catch (InstantiationException x) { throw new ServiceConfigurationError(null, x); } catch (SecurityException x) { throw new ServiceConfigurationError(null, x); } }
|
spi获取loadProviderAsService()
ServiceLoader是jdk实现的spi扩展,有两种配置的方式
- 直接通过类加载器加载类;
- 通过类加载器获取【META-INF/services/】目录下与类名一致的配置文件,文件中每行可以配置全限定类名,然后通过类名反射生成对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private static boolean loadProviderAsService() { ServiceLoader<SelectorProvider> sl = ServiceLoader.load(SelectorProvider.class, ClassLoader.getSystemClassLoader()); Iterator<SelectorProvider> i = sl.iterator(); for (;;) { try { if (!i.hasNext()) return false; provider = i.next(); return true; } catch (ServiceConfigurationError sce) { if (sce.getCause() instanceof SecurityException) { continue; } throw sce; } } }
|
统一获取方法provider()
依次获取,如果获取到就返回:
- 当前已经有啦;
- 通过环境变量配置的;
- 通过jdk的spi获取的;
- 默认通过sun.nio.ch.DefaultSelectorProvider.create()生成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static SelectorProvider provider() { synchronized (lock) { if (provider != null) return provider; return AccessController.doPrivileged( new PrivilegedAction<SelectorProvider>() { public SelectorProvider run() { if (loadProviderFromProperty()) return provider; if (loadProviderAsService()) return provider; provider = sun.nio.ch.DefaultSelectorProvider.create(); return provider; } }); } }
|
抽象方法
1 2 3 4 5 6 7 8 9 10 11 12
| public abstract DatagramChannel openDatagramChannel() throws IOException; public abstract DatagramChannel openDatagramChannel(ProtocolFamily family) throws IOException; public abstract Pipe openPipe() throws IOException; public abstract AbstractSelector openSelector() throws IOException; public abstract ServerSocketChannel openServerSocketChannel() throws IOException; public abstract SocketChannel openSocketChannel() throws IOException;
|
`