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 }