All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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> key) { registryBinderImpl.bindRegistryListener(matcher, key); } @Beta protected void bindRegistryListener(Matcher> matcher, RegistryListener 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