org.javabits.yar.guice.AbstractRegistryModule Maven / Gradle / Ivy
/*
* Copyright 2013 Romain Gilles
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.javabits.yar.guice;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.google.inject.*;
import com.google.inject.matcher.Matcher;
import java.lang.reflect.Method;
import static org.javabits.yar.guice.RegistrationBindingBuilderImpl.bindRegistration;
/**
* Extension of the support class {@code AbstractModule} that adds to the Guice EDSL
* features to work with Yar {@code Registry}.
* In Yar {@code Registry} three concepts works together:
*
* - Registering {@code Supplier} under an {@code Id}
* - Getting a or a list of {@code Supplier}(s) for a given {@code Id}
* - And then listening mutating operation on the {@code Registry}
*
* This class will help you to work with those concepts. You should subclass this module
* to work with the registry in the {@link #configureRegistry()} method.
*
* Date: 2/28/13
*
*
* @author Romain Gilles
*/
public abstract class AbstractRegistryModule extends AbstractModule {
private RegistryBinder registryBinderImpl;
@Override
protected final void configure() {
registryBinderImpl = new RegistryBinderImpl(super.binder());
doBeforeConfiguration();
configureRegistry();
bindProviderMethods();
}
void doBeforeConfiguration() {
}
private void bindProviderMethods() {
for (Method method : this.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(Register.class) && method.isAnnotationPresent(Provides.class)) {
bindRegistration(binder(), Key.get(method.getGenericReturnType()));
}
}
}
/**
* Registry Management EDSL
* Guice injector:
*
* Guice.createInjector(..., new AbstractRegistryModule() {
* protected void configureRegistry() {
* register(MyProvidedInterface.class).to(MyImplementation.class);
* bind(MyRequiredInterface.class).toRegistry();
* ...
* }
* })
*
* Note: You must have one and only one {@link RegistryModule} in your
* {@code Injector} construction process. You may need to have a look to this class documentation
* to follow the initialization process.
*
* Getting Supplier(s)
* Your component may need services that are located in the registry.
* Bind service from registry
* Imagine that you required a {@code DataSource} provided by a other component.
* Simplest
* {@code bind(DataSource.class).toRegistry();}
* Named binding
* {@code bind(DataSource.class).annotatedWith(Names.named("data-source-xyz")).toRegistry();}
* Annotated binding
* {@code bind(DataSource.class).annotatedWith(DataSourceXYZAnnotation.class).toRegistry();}
* TypeLiteral or Key binding
* {@literal
* // literal
* bind(new TypeLiteral(){}).toRegistry();
* // key
* bind(Key.get(DataSource.class, Names.named("data-source-xyz"))).toRegistry();
* }
* Bind a Iterable / Collection / List
* The {@code Registry} can return List of suppliers for a given Id.
* You have a translation of this feature in this EDSL.
* You can bind {@code Iterable} / {@code Collection} / {@code List} of both direct target
* type {@code T} or {@code Supplier} as follow:
* {@literal
* //direct
* bind(new TypeLiteral>(){}).toRegistry();
* bind(new TypeLiteral>(){}).toRegistry();
* bind(new TypeLiteral>(){}).toRegistry();
* //through supplier
* bind(new TypeLiteral>>(){}).toRegistry();
* bind(new TypeLiteral>>(){}).toRegistry();
* bind(new TypeLiteral>>(){}).toRegistry();
* }
*
* Registering service
* Simplest
* {@code register(DataSource.class).to(MyDataSourcePool.class);}
* Named registration
* {@code register(DataSource.class).annotatedWith(Names.named("data-source-xyz")).to(MyDataSourcePool.class);}
* Annotated registration
* {@code register(DataSource.class).annotatedWith(DataSourceXYZAnnotation.class).to(MyDataSourcePool.class);}
* TypeLiteral or Key registration
* {@literal
* // literal
* register(new TypeLiteral(){}).to(MyDataSourcePool.class);
* // key
* register(Key.get(DataSource.class, Names.named("data-source-xyz"))).to(MyDataSourcePool.class);
* }
* Providers registration
* The EDSL extansion also fully support {@code Provider} and method {@code Provides} annotation.
*
* Guice.createInjector(..., new AbstractRegistryModule() {
* protected void configureRegistry() {
* register(MyProvidedInterface.class).to(MyImplementation.class);
* ...
* }
* {@literal @Provides}
* {@literal @Register}
* public DataSource myDataSource() {
* return new MyDataSourcePool();
* }
* })
*
* Collections warning
* There is no corresponding feature with the opposite bind functionality.
* You cannot register more than one supplier at a time.
*
* Listening registry events
*
*
* @see RegistryModule
*/
protected abstract void configureRegistry();
@Override
protected RegistryBinder binder() {
Preconditions.checkState(registryBinderImpl != null, "Binder is not defined before configuration start");
return registryBinderImpl;
}
@Beta
protected void bindRegistryListener(Matcher> matcher, Key extends RegistryListener super T>> key) {
registryBinderImpl.bindRegistryListener(matcher, key);
}
@Beta
protected void bindRegistryListener(Matcher> matcher, RegistryListener super T> listener) {
registryBinderImpl.bindRegistryListener(matcher, listener);
}
protected RegistrationLinkedBindingBuilder register(Key key) {
return registryBinderImpl.register(key);
}
protected RegistrationAnnotatedBindingBuilder register(TypeLiteral typeLiteral) {
return registryBinderImpl.register(typeLiteral);
}
// TODO cannot be scoped
protected RegistrationAnnotatedBindingBuilder register(Class type) {
return registryBinderImpl.register(type);
}
@Override
protected RegistryLinkedBindingBuilder bind(Key key) {
return registryBinderImpl.bind(key);
}
@Override
protected RegistryAnnotatedBindingBuilder bind(TypeLiteral typeLiteral) {
return registryBinderImpl.bind(typeLiteral);
}
@Override
protected RegistryAnnotatedBindingBuilder bind(Class clazz) {
return registryBinderImpl.bind(clazz);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy