The org.apache.onami.spi.ServiceLoaderModule provides APIs to bind Services to Provided discovered via SPI pattern.
Given an hypothetical CreditCardProcessor:
package com.acme;
public interface CreditCardProcessor
{
void doSomething();
}With related implementations:
package com.acme.first;
@javax.inject.Named( "Visa" ) // any @javax.inject.Qualifier or @com.google.inject.BindingAnnotation annotated annotation
public final class VisaCreditCardProcessor
implements CreditCardProcessor
{
public void doSomething()
{
// ...
}
}and
package com.acme.second;
@javax.inject.Named( "MasterCard" ) // any @javax.inject.Qualifier or @com.google.inject.BindingAnnotation annotated annotation
public final class MasterCardCreditCardProcessor
implements CreditCardProcessor
{
public void doSomething()
{
// ...
}
}Then define the SPI in META-INF/services/com.acme.CreditCardProcessor file(s):
# created by Jack Bauer in less than 24h com.acme.first.VisaCreditCardProcessor com.acme.second.MasterCardCreditCardProcessor # EOL comment # comments and blank lines supported #
Then users can require Services binding discovering implementation(s) with the service loader:
import static com.google.inject.Guice.createInjector;
import com.acme.FooService;
import com.google.inject.Injector;
import org.apache.onami.spi.ServiceLoaderModule;
...
Injector injector = createInjector( new ServiceLoaderModule()
{
@Override
protected void configureServices()
{
discover( CreditCardProcessor.class ); //.fromClassLoader( ClassLoader classLoader );
}
} );and the require injections somewhere else:
public class PowerTool
{
@Inject
@javax.inject.Named( "MasterCard" )
private CreditCardProcessor creditCardProcessor;
// setters and algorithms omitted
}if a service is not annotated by a qualifier/binding annotation, i.e.
package com.acme;
public final class DefaultCreditCardProcessor
implements CreditCardProcessor
{
public void doSomething()
{
// ...
}
}Then defined the SPI in META-INF/services/com.acme.CreditCardProcessor file:
# created by Jack Bauer in less than 24h com.acme.DefaultCreditCardProcessor
it is enough requiring its injection:
public class PowerTool
{
@Inject
// this is bound to com.acme.DefaultCreditCardProcessor
private CreditCardProcessor creditCardProcessor;
// setters and algorithms omitted
}Services implementations can be annotated with whatever annotation which, at their time, are annotated with a @javax.inject.Qualifier or @com.google.inject.BindingAnnotation annotation; i.e. given the following annotations:
@com.google.inject.BindingAnnotation
@Retention( RUNTIME )
@Target( { FIELD, TYPE } )
public @interface Visa
{}and
@com.google.inject.BindingAnnotation
@Retention( RUNTIME )
@Target( { FIELD, TYPE } )
public @interface MasterCard
{}users can annotate services implementations:
package com.acme.first;
@Visa
public final class VisaCreditCardProcessorImpl
implements CreditCardProcessor
{
public void doSomething()
{
// ...
}
}and
package com.acme.second;
@MasterCard
public final class MasterCardCreditCardProcessorImpl
implements CreditCardProcessor
{
public void doSomething()
{
// ...
}
}Then define the SPI in META-INF/services/com.acme.CreditCardProcessor file(s):
# created by Jack Bauer in less than 24h com.acme.first.VisaCreditCardProcessorImpl com.acme.second.MasterCardCreditCardProcessorImpl
Injections can be required by qualifying the injections:
public class PowerTool
{
@Inject
@Visa
private CreditCardProcessor creditCardProcessor;
@Inject
@MasterCard
private CreditCardProcessor creditCardProcessor;
// setters and algorithms omitted
}