How to inject package private classes using Guice
Firstly i like what Guice does however i have also like to make as few classes in my system public. All services in my system are package private w/ only the interface public. This presents a few problems for Guice if one does not use a provider. I would prefer some alternative that allows me to provide a strategy to do the following:
- for component C
- requires dependencies X, Y, Z
- call this method w/ X, Y, Z to create instance.
.. repeat again for all components.
In step 2 of the above psuedo code Guice now scans for @inject annotations. If this strategy was available I could decide how id like to find my component's dependencies in a generic way.
Unfortunately Module.bind just doesnt work because it works w/ classes literals.
The strategy interface for the above might look like this
interface ComponentDiscoverer {
Set<ComponentDefinition> components();
}
interface ComponentDefinition<T> {
List<RequiredDependency> requiredDependencies(); // similar to Guice's Key
<T> create( List<SatisfiedDependency> dependencies ); // factory method.
}
- Guice gets all components by calling a r开发者_StackOverflow社区egistered ComponentDiscoverer.
- It then calls the registered ComponentDiscoverer.components();
- For each ComponentDefinition.requiredDependencies()
- on demand call ComponentDefinition.create
Is this any built into Guice way or third party library to achieve the above ?
SAMPLE
package companyX;
public interface Service {
void execute();
}
package companyX;
package private class ServiceImpl implements Service {
static ServiceImpl create( Dependency dependency){
return new ServiceImpl( dependency );
}
private ServiceImpl( Dependency dependency ){
}
void execute();
}
package companyX;
package private class ServiceImpl2 implements Service2{
}
package companyX;
public class Factory {
Service alpha( Dependency ){
return ServiceImpl.create( dependency );
}
Service beta( DifferentDependency ){
// boring left out
}
Service2 gamma( AnotherDifferentDependency);
}
My module lives in a different package and all creation goes thru Fatory because everything else is package private.
You shouldn't have just one Module
unless your application is very simple. You should have a module for each package that you have package-private classes you want to use in. This allows you to bind those package-private classes to the public interfaces. This is a standard practice for using Guice, and it's mentioned in the Keep Constructors Hidden section of the documentation.
With a module in the package, you just need normal @Inject
able constructors or provider methods:
@Provides @Alpha Service alpha(Dependency dependency) {
return ServiceImpl.create(dependency);
}
精彩评论