elasticsearch采用google的guice框架进行依赖注入。与spring相比较,guice省去了xml形式的配置文件,而是采用编码到module中进行管理,同时采用标注的形式进行注入。个人觉得这种代码组织方式没有xml文件方式直观,因此给阅读源代码带来一定困难。那么elasticsearch是如何使用的guice进行代码管理的呢?在elasticsearch启动的时候,会实例化一个InternalNode实例,该实例的构造方法如下表
代码1
publicInternalNode(SettingspSettings,booleanloadConfigSettings)throwsElasticSearchException{ Tuple<Settings,Environment>tuple=InternalSettingsPerparer.prepareSettings(pSettings,loadConfigSettings); Versionversion=Version.CURRENT; ESLoggerlogger=Loggers.getLogger(Node.class,tuple.v1().get("name")); logger.info("version[{}], pid[{}],build[{}/{}]",version,JvmInfo.jvmInfo().pid(),Build.CURRENT.hashShort(),Build.CURRENT.timestamp()); logger.info("initializing..."); if(logger.isDebugEnabled()){ Environmentenv=tuple.v2(); logger.debug("using home [{}], config[{}], data [{}], logs [{}], work [{}], plugins [{}]", env.homeFile(),env.configFile(),Arrays.toString(env.dataFiles()),env.logsFile(), env.workFile(),env.pluginsFile()); } this.pluginsService=newPluginsService(tuple.v1(),tuple.v2()); this.settings=pluginsService.updatedSettings(); this.environment=tuple.v2(); CompressorFactory.configure(settings); NodeEnvironmentnodeEnvironment=newNodeEnvironment(this.settings,this.environment); ModulesBuildermodules=newModulesBuilder(); modules.add(newVersion.Module(version)); modules.add(newCacheRecyclerModule(settings)); modules.add(newPluginsModule(settings,pluginsService)); modules.add(newSettingsModule(settings)); modules.add(newNodeModule(this)); modules.add(newNetworkModule()); modules.add(newNodeCacheModule(settings)); modules.add(newScriptModule(settings)); modules.add(newEnvironmentModule(environment)); modules.add(newNodeEnvironmentModule(nodeEnvironment)); modules.add(newClusterNameModule(settings)); modules.add(newThreadPoolModule(settings)); modules.add(newDiscoveryModule(settings)); modules.add(newClusterModule(settings)); modules.add(newRestModule(settings)); modules.add(newTransportModule(settings)); if(settings.getAsBoolean("http.enabled",true)){ modules.add(newHttpServerModule(settings)); } modules.add(newRiversModule(settings)); modules.add(newIndicesModule(settings)); modules.add(newSearchModule()); modules.add(newActionModule(false)); modules.add(newMonitorModule(settings)); modules.add(newGatewayModule(settings)); modules.add(newNodeClientModule()); modules.add(newBulkUdpModule()); modules.add(newShapeModule()); modules.add(newPercolatorModule());
injector=modules.createInjector(); client=injector.getInstance(Client.class); logger.info("initialized"); } |
从上述源代码中可以看到,elasticsearch定义了很多module类来管理不同功能的代码,在实例化InternalNode的过程中,完成了所有代码的初始化、依赖注入等过程。具体每个module类对应的功能可以参考其命名(也可以参考这篇博文:http://blog.csdn.net/laigood/article/details/7997529)
以ClusterModule为例,在代码中,我们可以看到其绑定了如下多的单例。或者可以理解为这些类就放入guice框架里进行托管了。因此从guice中拿对象的时候,其都是由guice注入好的对象。(和spring的方式一样)
代码2
protectedvoidconfigure(){ bind(DiscoveryNodeService.class).asEagerSingleton(); bind(ClusterService.class).to(InternalClusterService.class).asEagerSingleton();
bind(MetaDataService.class).asEagerSingleton(); bind(MetaDataCreateIndexService.class).asEagerSingleton(); bind(MetaDataDeleteIndexService.class).asEagerSingleton(); bind(MetaDataIndexStateService.class).asEagerSingleton(); bind(MetaDataMappingService.class).asEagerSingleton(); bind(MetaDataIndexAliasesService.class).asEagerSingleton(); bind(MetaDataUpdateSettingsService.class).asEagerSingleton(); bind(MetaDataIndexTemplateService.class).asEagerSingleton();
bind(RoutingService.class).asEagerSingleton();
bind(ShardStateAction.class).asEagerSingleton(); bind(NodeIndexCreatedAction.class).asEagerSingleton(); bind(NodeIndexDeletedAction.class).asEagerSingleton(); bind(NodeMappingCreatedAction.class).asEagerSingleton(); bind(NodeMappingRefreshAction.class).asEagerSingleton(); bind(MappingUpdatedAction.class).asEagerSingleton(); bind(NodeAliasesUpdatedAction.class).asEagerSingleton(); bind(NodeIndicesStateUpdatedAction.class).asEagerSingleton(); } |
以上面代码中的一个类NodeIndexCreatedAction为例,其构造方法如下所示:
代码3
@Inject publicNodeIndexCreatedAction(Settingssettings, ThreadPoolthreadPool, TransportServicetransportService,ClusterServiceclusterService){ super(settings); this.threadPool=threadPool; this.transportService=transportService; this.clusterService=clusterService; transportService.registerHandler( NodeIndexCreatedTransportHandler.ACTION, newNodeIndexCreatedTransportHandler() ); } |
从上面的代码中,可以看出在实例化NodeIndexCreatedAction单例的过程中,guice为该单例注入了settings、threadPool、transportService以及clusterService等对象。同时注意加粗的代码,在初始化的过程中,本NodeIndexCreatedAction对象会向transportService注册一个handler。该handler是用于处理netty(elasticsearch采用netty进行信息的传输)接收的消息时使用的,在稍后的博文中会进行介绍。