ElasticSearch 源码之Guice

本文探讨了Elasticsearch如何利用Guice实现依赖注入及模块化管理,详细解析了其内部组件构造流程,并以TransportClient初始化为例,展示了Guice在实际场景中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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<Module> {
    private final List<Module> modules = new ArrayList<>();
    public ModulesBuilder add(Module... newModules) {
        Collections.addAll(modules, newModules);
        return this;
    }
    @Override
    public Iterator<Module> 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 初始化情况展开说明:

    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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值