1 /* 2 * Copyright (C) 2015 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.inject.daggeradapter; 17 18 import com.google.common.base.MoreObjects; 19 import com.google.inject.Binder; 20 import com.google.inject.Module; 21 import com.google.inject.internal.ProviderMethodsModule; 22 import com.google.inject.spi.ModuleAnnotatedMethodScanner; 23 import java.util.Arrays; 24 25 /** 26 * A utility to adapt classes annotated with {@link @dagger.Module} such that their 27 * {@link @dagger.Provides} methods can be properly invoked by Guice to perform their provision 28 * operations. 29 * 30 * <p>Simple example: 31 * 32 * <pre>{@code 33 * Guice.createInjector(...other modules..., DaggerAdapter.from(new SomeDaggerAdapter())); 34 * }</pre> 35 * 36 * <p>Some notes on usage and compatibility. 37 * 38 * <ul> 39 * <li>Dagger provider methods have a "SET_VALUES" provision mode not supported by Guice. 40 * <li>MapBindings are not yet implemented (pending). 41 * <li>Be careful about stateful modules. In contrast to Dagger (where components are expected to be 42 * recreated on-demand with new Module instances), Guice typically has a single injector with a 43 * long lifetime, so your module instance will be used throughout the lifetime of the entire 44 * app. 45 * <li>Dagger 1.x uses {@link @Singleton} for all scopes, including shorter-lived scopes like 46 * per-request or per-activity. Using modules written with Dagger 1.x usage in mind may result 47 * in mis-scoped objects. 48 * <li>Dagger 2.x supports custom scope annotations, but for use in Guice, a custom scope 49 * implementation must be registered in order to support the custom lifetime of that annotation. 50 * </ul> 51 * 52 * @author cgruber@google.com (Christian Gruber) 53 */ 54 public final class DaggerAdapter { 55 /** 56 * Returns a guice module from a dagger module. 57 * 58 * <p>Note: At present, it does not honor {@code @Module(includes=...)} directives. 59 */ from(Object... daggerModuleObjects)60 public static Module from(Object... daggerModuleObjects) { 61 // TODO(cgruber): Gather injects=, dedupe, factor out instances, instantiate the rest, and go. 62 return new DaggerCompatibilityModule(daggerModuleObjects); 63 } 64 65 /** 66 * A Module that adapts Dagger {@code @Module}-annotated types to contribute configuration to an 67 * {@link com.google.inject.Injector} using a dagger-specific {@link 68 * ModuleAnnotatedMethodScanner}. 69 */ 70 private static final class DaggerCompatibilityModule implements Module { 71 private final Object[] daggerModuleObjects; 72 DaggerCompatibilityModule(Object... daggerModuleObjects)73 private DaggerCompatibilityModule(Object... daggerModuleObjects) { 74 this.daggerModuleObjects = daggerModuleObjects; 75 } 76 77 @Override configure(Binder binder)78 public void configure(Binder binder) { 79 for (Object module : daggerModuleObjects) { 80 binder.install(ProviderMethodsModule.forModule(module, DaggerMethodScanner.INSTANCE)); 81 } 82 } 83 84 @Override toString()85 public String toString() { 86 return MoreObjects.toStringHelper(this) 87 .add("modules", Arrays.asList(daggerModuleObjects)) 88 .toString(); 89 } 90 } 91 DaggerAdapter()92 private DaggerAdapter() {} 93 } 94