ElasticSearch 源码之Guice

es 使用google开源的依赖注入框架guice,这个项目号称比spring快100倍,不过由于其代码比较简洁,这样的结论是很有可能的。es 是直接把guice的源码放到自己的包内(es把很多开源项目的代码都直接集成到自己项目中,省得依赖一堆的jar包,也使es的jar包达到差不多10M),它位于 org.elasticsearch.common.inject 目录下。

es 里面的组件基本都实现了模块化管理,对guice进行了简单的封装,通过 ModulesBuilder 类构建es的模块,一个es节点模块有:

//源自org.elasticsearch.common.inject;
public class ModulesBuilder implements Iterable {
    private final List modules = new ArrayList<>();
    public ModulesBuilder add(Module... newModules) {
        Collections.addAll(modules, newModules);
        return this;
    }
    @Override
    public Iterator iterator() {
        return modules.iterator();
    }
    public Injector createInjector() {
        Injector injector = Guice.createInjector(modules);
        ((InjectorImpl) injector).clearCache();
        // in ES, we always create all instances as if they are eager singletons
        // this allows for considerable memory savings (no need to store construction info) as well as cycles
        ((InjectorImpl) injector).readOnlyAllSingletons();
        return injector;
    }
}
//通过下面伪代码进行模块化
ModulesBuilder modules = new ModulesBuilder();
modules.add(new ToolModule());
modules.add(new HumanModule());
Injector injector = modules.createInjector(); // 注入所有module下的实例
Person instance = injector.getInstance(Person.class);
  • PluginsModule:插件模块
  • SettingsModule:设置参数模块
  • NodeModule:节点模块
  • NetworkModule:网络模块
  • NodeCacheModule:缓存模块
  • ScriptModule:脚本模块
  • JmxModule:jmx模块
  • EnvironmentModule:环境模块
  • NodeEnvironmentModule:节点环境模块
  • ClusterNameModule:集群名模块
  • ThreadPoolModule:线程池模块
  • DiscoveryModule:自动发现模块
  • ClusterModule:集群模块
  • RestModule:rest模块
  • TransportModule:tcp模块
  • HttpServerModule:http模块
  • IndicesModule:索引模块
  • SearchModule:搜索模块
  • ActionModule:行为模块
  • MonitorModule:监控模块
  • GatewayModule:持久化模块
  • NodeClientModule:客户端模块

下面就TransportModuleTransportClient 初始化情况展开说明:

ElasticSearch 源码之Guice_第1张图片

    public TransportClient build() {
        Settings settings = InternalSettingsPreparer.prepareSettings(this.settings);
        settings = settingsBuilder()
                .put(NettyTransport.PING_SCHEDULE, "5s") // enable by default the transport schedule ping interval
                .put(settings)
                .put("network.server", false)
                .put("node.client", true)
                .put(CLIENT_TYPE_SETTING, CLIENT_TYPE)
                .build();

        PluginsService pluginsService = new PluginsService(settings, null, null, pluginClasses);
        this.settings = pluginsService.updatedSettings();

        Version version = Version.CURRENT;

        final ThreadPool threadPool = new ThreadPool(settings);
        NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry();

        boolean success = false;
        try {
            ModulesBuilder modules = new ModulesBuilder();
            modules.add(new Version.Module(version));
            // plugin modules must be added here, before others or we can get crazy injection errors...
            for (Module pluginModule : pluginsService.nodeModules()) {
                modules.add(pluginModule);
            }
            modules.add(new PluginsModule(pluginsService));
            modules.add(new SettingsModule(this.settings));
            modules.add(new NetworkModule(namedWriteableRegistry));
            modules.add(new ClusterNameModule(this.settings));
            modules.add(new ThreadPoolModule(threadPool));
            modules.add(new TransportModule(this.settings, namedWriteableRegistry));
            modules.add(new SearchModule() {
                @Override
                protected void configure() {
                    // noop
                }
            });
            modules.add(new ActionModule(true));
            modules.add(new ClientTransportModule(hostFailedListener));
            modules.add(new CircuitBreakerModule(this.settings));

            pluginsService.processModules(modules);

            Injector injector = modules.createInjector();
            final TransportService transportService = injector.getInstance(TransportService.class);
            transportService.start();
            transportService.acceptIncomingRequests();

            TransportClient transportClient = new TransportClient(injector); // 初始化TransportClient对象
            success = true;
            return transportClient;
        } finally {
            if (!success) {
                ThreadPool.terminate(threadPool, 10, TimeUnit.SECONDS);
            }
        }
    }
//settings模块,源自org.elasticsearch.common.settings
public class SettingsModule implements Module {
    public SettingsModule(Settings settings, Setting... additionalSettings) {
        this(settings, Arrays.asList(additionalSettings), Collections.emptyList());
    }
    @Override
    public void configure(Binder binder) {
        binder.bind(Settings.class).toInstance(settings);
        binder.bind(SettingsFilter.class).toInstance(settingsFilter);
        binder.bind(ClusterSettings.class).toInstance(clusterSettings);
        binder.bind(IndexScopedSettings.class).toInstance(indexScopedSettings);
    }
}

看到了吧,es的模块化的解决方案主要是依靠Guice,而优秀的java的模块化解决方案也是我们值得学习与借鉴的。

引用资料

IBM 通过 Guice 进行依赖项注入

guice-github-wiki

你可能感兴趣的:(最新,elasticsearch,搜索技术)