Break out an inject package, looks like this may get a little wierd.
Rename CommonModule -> RootModule, inject HBaseComponentConfig.

The config injection is tricky.  We are simultaneously catering to two cases, expressed as the if inside the new RequestModule (which is the extraction of the anonymous module from scopeAndInject.)

When the config is passed at component construction, RequestModule binds it literally and we're done.

When it is not, RequestModule binds ConfigProvider instead, which knows how to parse a new config from json.

Either way, the config member of the base class now has a @Inject annotation, and the lazy initialization in the getter is gone.

In the default-constructor case, we already know we don't use the config until the RequestModule is active, and so the json parsing binding is live when injection takes place: the null config member gets correctly injected.

In the passed-at-construction case, the member is already populated, but gets *injectect with itself* again.  We can't avoid this (there is no "condtional" annotation in java), but it provably overwrites the member with the value it already had: a no-op.
Inline ConfigProvider.
Rename ConfigProvider -> ComponentCommonJsonConfigProvider.
Drop a manual injection method.
Provide input and output bindings.
This can be private.
Provide the flusher thread pool.
Provide the ScheduledExecutorService.

This is tricky, since we don't want to include the "heavy" thread dependency in our RequestModule (which is used in unit tests.)

So, introduce a ScheduledExecutorServiceFactory interface, bound in ProductionModule and the fixture, and use it to provide a ScheduledExecutorService of the expected size.