Remove InjectorBuilder in favor of methods in Binder.

git-svn-id: https://google-guice.googlecode.com/svn/trunk@1457 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/core/src/com/google/inject/Binder.java b/core/src/com/google/inject/Binder.java
index c5416c4..10ae239 100644
--- a/core/src/com/google/inject/Binder.java
+++ b/core/src/com/google/inject/Binder.java
@@ -25,6 +25,7 @@
 import com.google.inject.spi.TypeListener;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 
 /**
  * Collects configuration information (primarily <i>bindings</i>) which will be
@@ -407,4 +408,49 @@
    * @since 2.0
    */
   PrivateBinder newPrivateBinder();
+
+  /**
+   * Instructs the Injector that bindings must be listed in a Module in order to
+   * be injected. Classes that are not explicitly bound in a module cannot be
+   * injected. Bindings created through a linked binding (
+   * <code>bind(Foo.class).to(FooImpl.class)</code>) are allowed, but the
+   * implicit binding (<code>FooImpl</code>) cannot be directly injected unless
+   * it is also explicitly bound (<code>bind(FooImpl.class</code>).
+   * <p>
+   * Tools can still retrieve bindings for implicit bindings (bindings created
+   * through a linked binding) if explicit bindings are required, however
+   * {@link Binding#getProvider} will fail.
+   * <p>
+   * By default, explicit bindings are not required.
+   * <p>
+   * If a parent injector requires explicit bindings, then all child injectors
+   * (and private modules within that injector) also require explicit bindings.
+   * If a parent does not require explicit bindings, a child injector or private
+   * module may optionally declare itself as requiring explicit bindings. If it
+   * does, the behavior is limited only to that child or any grandchildren. No
+   * siblings of the child will require explicit bindings.
+   * <p>
+   * If the parent did not require explicit bindings but the child does, it is
+   * possible that a linked binding in the child may add a JIT binding to the
+   * parent. The child will not be allowed to reference the target binding
+   * directly, but the parent and other children of the parent may be able to.
+   * 
+   * @since 3.0
+   */
+  void requireExplicitBindings();
+  
+  /**
+   * Prevents Guice from constructing a {@link Proxy} when a circular dependency
+   * is found.  By default, circular proxies are not disabled.
+   * <p>
+   * If a parent injector disables circular proxies, then all child injectors
+   * (and private modules within that injector) also disable circular proxies.
+   * If a parent does not disable circular proxies, a child injector or private
+   * module may optionally declare itself as disabling circular proxies. If it
+   * does, the behavior is limited only to that child or any grandchildren. No
+   * siblings of the child will disable circular proxies.
+   * 
+   * @since 3.0
+   */
+  void disableCircularProxies();
 }
diff --git a/core/src/com/google/inject/Guice.java b/core/src/com/google/inject/Guice.java
index 03e652a..3c6da0f 100644
--- a/core/src/com/google/inject/Guice.java
+++ b/core/src/com/google/inject/Guice.java
@@ -18,10 +18,12 @@
 
 import java.util.Arrays;
 
+import com.google.inject.internal.InternalInjectorCreator;
+
 
 /**
  * The entry point to the Guice framework. Creates {@link Injector}s from
- * {@link Module}s.  For advanced usage, see {@link InjectorBuilder}.
+ * {@link Module}s.
  *
  * <p>Guice supports a model of development that draws clear boundaries between
  * APIs, Implementations of these APIs, Modules which configure these
@@ -51,8 +53,7 @@
   private Guice() {}
 
   /**
-   * Creates an injector for the given set of modules. To create an injector
-   * with a {@link Stage} or other options, see {@link InjectorBuilder}.
+   * Creates an injector for the given set of modules.
    *
    * @throws CreationException if one or more errors occur during injector
    *     construction
@@ -62,8 +63,7 @@
   }
 
   /**
-   * Creates an injector for the given set of modules. To create an injector
-   * with a {@link Stage} or other options, see {@link InjectorBuilder}.
+   * Creates an injector for the given set of modules.
    *
    * @throws CreationException if one or more errors occur during injector
    *     creation
@@ -74,7 +74,7 @@
 
   /**
    * Creates an injector for the given set of modules, in a given development
-   * stage. Use {@link InjectorBuilder} for advanced injector creation.
+   * stage.
    *
    * @throws CreationException if one or more errors occur during injector
    *     creation.
@@ -85,14 +85,14 @@
 
   /**
    * Creates an injector for the given set of modules, in a given development
-   * stage. Use {@link InjectorBuilder} for advanced injector creation.
+   * stage.
    *
    * @throws CreationException if one or more errors occur during injector
    *     construction
    */
   public static Injector createInjector(Stage stage,
       Iterable<? extends Module> modules) {
-    return new InjectorBuilder()
+    return new InternalInjectorCreator()
         .stage(stage)
         .addModules(modules)
         .build();
diff --git a/core/src/com/google/inject/InjectorBuilder.java b/core/src/com/google/inject/InjectorBuilder.java
deleted file mode 100644
index b0f763f..0000000
--- a/core/src/com/google/inject/InjectorBuilder.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.google.inject;
-
-import com.google.inject.internal.InternalInjectorCreator;
-import java.lang.reflect.Proxy;
-import java.util.Arrays;
-
-/**
- * The advanced entry point to the Guice framework. Creates {@link Injector}s from
- * {@link Module}s, allowing many options to be configured for the Injector.
- *
- * <p>Guice supports a model of development that draws clear boundaries between
- * APIs, Implementations of these APIs, Modules which configure these
- * implementations, and finally Applications which consist of a collection of
- * Modules. It is the Application, which typically defines your {@code main()}
- * method, that bootstraps the Guice Injector using the {@code Guice} class, as
- * in this example:
- * <pre>
- *     public class FooApplication {
- *       public static void main(String[] args) {
- *         Injector injector = new InjectorBuilder().
- *             .stage(Stage.PRODUCTION)
- *             . . . 
- *             .addModules(
- *                new ModuleA(),
- *                new ModuleB(),
- *                . . .
- *                new FooApplicationFlagsModule(args)
- *             )
- *             .build();
- *         );
- *
- *         // Now just bootstrap the application and you're done
- *         FooStarter starter = injector.getInstance(FooStarter.class);
- *         starter.runApplication();
- *       }
- *     }
- * </pre>
- * 
- * @since 3.0
- */
-public final class InjectorBuilder {
-  
-  private final InternalInjectorCreator creator = new InternalInjectorCreator();
-  
-  private Stage stage = Stage.DEVELOPMENT;
-  private boolean jitDisabled = false;
-  private boolean allowCircularProxy = true;
-  
-  /**
-   * Sets the stage for the injector. If the stage is {@link Stage#PRODUCTION}, 
-   * singletons will be eagerly loaded when the Injector is built.
-   */
-  public InjectorBuilder stage(Stage stage) {
-    this.stage = stage;
-    return this;
-  }
-
-  /**
-   * If explicit bindings are required, then classes that are not explicitly
-   * bound in a module cannot be injected. Bindings created through a linked
-   * binding (<code>bind(Foo.class).to(FooImpl.class)</code>) are allowed, but
-   * the implicit binding (FooImpl) cannot be directly injected unless it is
-   * also explicitly bound.
-   * 
-   * Tools can still retrieve bindings for implicit bindings (bindings created
-   * through a linked binding) if explicit bindings are required, however
-   * {@link Binding#getProvider} cannot be used.
-   * 
-   * By default, explicit bindings are not required.
-   */
-  public InjectorBuilder requireExplicitBindings() {
-    this.jitDisabled = true;
-    return this;
-  }
-  
-  /**
-   * Prevents Guice from constructing a {@link Proxy} when a circular dependency
-   * is found.
-   */
-  public InjectorBuilder disableCircularProxies() {
-    this.allowCircularProxy = false;
-    return this;
-  }
-
-  /** Adds more modules that will be used when the Injector is created. */
-  public InjectorBuilder addModules(Iterable<? extends Module> modules) {
-    creator.addModules(modules);
-    return this;
-  }
-  
-  /** Adds more modules that will be used when the Injector is created. */
-  public InjectorBuilder addModules(Module... modules) {
-    creator.addModules(Arrays.asList(modules));
-    return this;
-  }
-
-  /** Builds the injector. */
-  public Injector build() {
-    creator.injectorOptions(new InternalInjectorCreator.InjectorOptions(stage, jitDisabled, allowCircularProxy));
-    return creator.build();
-  }
-
-}
\ No newline at end of file
diff --git a/core/src/com/google/inject/internal/AbstractProcessor.java b/core/src/com/google/inject/internal/AbstractProcessor.java
index 05881f2..063b117 100644
--- a/core/src/com/google/inject/internal/AbstractProcessor.java
+++ b/core/src/com/google/inject/internal/AbstractProcessor.java
@@ -16,18 +16,8 @@
 
 package com.google.inject.internal;
 
-import com.google.inject.Binding;
+import com.google.inject.spi.DefaultElementVisitor;
 import com.google.inject.spi.Element;
-import com.google.inject.spi.ElementVisitor;
-import com.google.inject.spi.InjectionRequest;
-import com.google.inject.spi.MembersInjectorLookup;
-import com.google.inject.spi.Message;
-import com.google.inject.spi.PrivateElements;
-import com.google.inject.spi.ProviderLookup;
-import com.google.inject.spi.ScopeBinding;
-import com.google.inject.spi.StaticInjectionRequest;
-import com.google.inject.spi.TypeConverterBinding;
-import com.google.inject.spi.TypeListenerBinding;
 import java.util.Iterator;
 import java.util.List;
 
@@ -40,7 +30,7 @@
  *
  * @author jessewilson@google.com (Jesse Wilson)
  */
-abstract class AbstractProcessor implements ElementVisitor<Boolean> {
+abstract class AbstractProcessor extends DefaultElementVisitor<Boolean> {
 
   protected Errors errors;
   protected InjectorImpl injector;
@@ -72,51 +62,9 @@
       this.injector = null;
     }
   }
-
-  public Boolean visit(Message message) {
-    return false;
-  }
-
-  /*if[AOP]*/
-  public Boolean visit(
-      com.google.inject.spi.InterceptorBinding interceptorBinding) {
-    return false;
-  }
-  /*end[AOP]*/
-
-  public Boolean visit(ScopeBinding scopeBinding) {
-    return false;
-  }
-
-  public Boolean visit(InjectionRequest<?> injectionRequest) {
-    return false;
-  }
-
-  public Boolean visit(StaticInjectionRequest staticInjectionRequest) {
-    return false;
-  }
-
-  public Boolean visit(TypeConverterBinding typeConverterBinding) {
-    return false;
-  }
-
-  public <T> Boolean visit(Binding<T> binding) {
-    return false;
-  }
-
-  public <T> Boolean visit(ProviderLookup<T> providerLookup) {
-    return false;
-  }
-
-  public Boolean visit(PrivateElements privateElements) {
-    return false;
-  }
-
-  public <T> Boolean visit(MembersInjectorLookup<T> lookup) {
-    return false;
-  }
-
-  public Boolean visit(TypeListenerBinding binding) {
+  
+  @Override
+  protected Boolean visitOther(Element element) {
     return false;
   }
 }
diff --git a/core/src/com/google/inject/internal/ConstructorBindingImpl.java b/core/src/com/google/inject/internal/ConstructorBindingImpl.java
index 03c47c6..10bc5a5 100644
--- a/core/src/com/google/inject/internal/ConstructorBindingImpl.java
+++ b/core/src/com/google/inject/internal/ConstructorBindingImpl.java
@@ -121,7 +121,7 @@
 
   @SuppressWarnings("unchecked") // the result type always agrees with the ConstructorInjector type
   public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
-    factory.allowCircularProxy = injector.options.allowCircularProxy;
+    factory.allowCircularProxy = !injector.options.disableCircularProxies;
     factory.constructorInjector
         = (ConstructorInjector<T>) injector.constructors.get(constructorInjectionPoint, errors);
   }
diff --git a/core/src/com/google/inject/internal/InjectorImpl.java b/core/src/com/google/inject/internal/InjectorImpl.java
index 6a1984a..a070573 100644
--- a/core/src/com/google/inject/internal/InjectorImpl.java
+++ b/core/src/com/google/inject/internal/InjectorImpl.java
@@ -21,7 +21,6 @@
 import com.google.inject.ConfigurationException;
 import com.google.inject.ImplementedBy;
 import com.google.inject.Injector;
-import com.google.inject.InjectorBuilder;
 import com.google.inject.Key;
 import com.google.inject.MembersInjector;
 import com.google.inject.Module;
@@ -29,8 +28,8 @@
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
 import com.google.inject.Scope;
+import com.google.inject.Stage;
 import com.google.inject.TypeLiteral;
-import com.google.inject.internal.InternalInjectorCreator.InjectorOptions;
 import com.google.inject.internal.util.ImmutableList;
 import com.google.inject.internal.util.ImmutableMap;
 import com.google.inject.internal.util.ImmutableSet;
@@ -63,11 +62,32 @@
  * Default {@link Injector} implementation.
  *
  * @author crazybob@google.com (Bob Lee)
- * @see InjectorBuilder
  */
 final class InjectorImpl implements Injector, Lookups {
   public static final TypeLiteral<String> STRING_TYPE = TypeLiteral.get(String.class);
   
+  /** Options that control how the injector behaves. */
+  static class InjectorOptions {
+    final Stage stage;
+    final boolean jitDisabled;
+    final boolean disableCircularProxies;
+    
+    InjectorOptions(Stage stage, boolean jitDisabled, boolean disableCircularProxies) {
+      this.stage = stage;
+      this.jitDisabled = jitDisabled;
+      this.disableCircularProxies = disableCircularProxies;
+    }
+    
+    @Override
+    public String toString() {
+      return new ToStringBuilder(getClass())
+          .add("stage", stage)
+          .add("jitDisabled", jitDisabled)
+          .add("disableCircularProxies", disableCircularProxies)
+          .toString();
+    }
+  }
+  
   /** some limitations on what just in time bindings are allowed. */
   enum JitLimitation { 
     /** does not allow just in time bindings */
@@ -212,7 +232,6 @@
   private <T> BindingImpl<T> getJustInTimeBinding(Key<T> key, Errors errors, JitLimitation jitType)
       throws ErrorsException {
 
-
     boolean jitOverride = isProvider(key) || isTypeLiteral(key) || isMembersInjector(key);
     if(options.jitDisabled && jitType == JitLimitation.NO_JIT && !jitOverride) {
       throw errors.jitDisabled(key).toException();
diff --git a/core/src/com/google/inject/internal/InjectorOptionsProcessor.java b/core/src/com/google/inject/internal/InjectorOptionsProcessor.java
new file mode 100644
index 0000000..c5da8c5
--- /dev/null
+++ b/core/src/com/google/inject/internal/InjectorOptionsProcessor.java
@@ -0,0 +1,69 @@
+/*

+ * Copyright (C) 2007 Google Inc.

+ *

+ * 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 com.google.inject.internal;

+

+import static com.google.inject.internal.util.Preconditions.checkNotNull;

+import static com.google.inject.internal.util.Preconditions.checkState;

+

+import com.google.inject.Stage;

+import com.google.inject.internal.InjectorImpl.InjectorOptions;

+import com.google.inject.spi.DisableCircularProxiesOption;

+import com.google.inject.spi.RequireExplicitBindingsOption;

+

+/**

+ * A processor to gather injector options.

+ *

+ * @author sameb@google.com (Sam Berlin)

+ */

+class InjectorOptionsProcessor extends AbstractProcessor {

+

+  private boolean disableCircularProxies = false;

+  private boolean jitDisabled = false;

+

+  InjectorOptionsProcessor(Errors errors) {

+    super(errors);

+  }

+

+  @Override

+  public Boolean visit(DisableCircularProxiesOption option) {

+    disableCircularProxies = true;

+    return true;

+  }

+

+  @Override

+  public Boolean visit(RequireExplicitBindingsOption option) {

+    jitDisabled = true;

+    return true;

+  }

+

+  InjectorOptions getOptions(Stage stage, InjectorOptions parentOptions) {

+    checkNotNull(stage, "stage must be set");

+    if(parentOptions == null) {

+      return new InjectorOptions(

+          stage,

+          jitDisabled,

+          disableCircularProxies);

+    } else {

+      checkState(stage == parentOptions.stage, "child & parent stage don't match");

+      return new InjectorOptions(

+          stage,

+          jitDisabled || parentOptions.jitDisabled,

+          disableCircularProxies || parentOptions.disableCircularProxies); 

+    }

+  }

+

+}

diff --git a/core/src/com/google/inject/internal/InjectorShell.java b/core/src/com/google/inject/internal/InjectorShell.java
index 87c6a9a..9086b9a 100644
--- a/core/src/com/google/inject/internal/InjectorShell.java
+++ b/core/src/com/google/inject/internal/InjectorShell.java
@@ -24,7 +24,7 @@
 import static com.google.inject.Scopes.SINGLETON;
 import com.google.inject.Singleton;
 import com.google.inject.Stage;
-import com.google.inject.internal.InternalInjectorCreator.InjectorOptions;
+import com.google.inject.internal.InjectorImpl.InjectorOptions;
 import com.google.inject.internal.util.ImmutableSet;
 import com.google.inject.internal.util.Lists;
 import static com.google.inject.internal.util.Preconditions.checkNotNull;
@@ -41,9 +41,9 @@
 import java.util.logging.Logger;
 
 /**
- * A partially-initialized injector. See {@link InjectorBuilder}, which uses this to build a tree
- * of injectors in batch.
- *
+ * A partially-initialized injector. See {@link InternalInjectorCreator}, which
+ * uses this to build a tree of injectors in batch.
+ * 
  * @author jessewilson@google.com (Jesse Wilson)
  */
 final class InjectorShell {
@@ -75,19 +75,21 @@
 
     private InjectorImpl parent;
     private InjectorOptions options;
+    private Stage stage;
 
     /** null unless this exists in a {@link Binder#newPrivateBinder private environment} */
     private PrivateElementsImpl privateElements;
+    
+    Builder stage(Stage stage) {
+      this.stage = stage;
+      return this;
+    }
 
     Builder parent(InjectorImpl parent) {
       this.parent = parent;
       this.state = new InheritingState(parent.state);
       this.options = parent.options;
-      return this;
-    }
-    
-    Builder setInjectorOptions(InjectorOptions options) {
-      this.options = options;
+      this.stage = options.stage;
       return this;
     }
 
@@ -103,8 +105,8 @@
       }
     }
     
-    InjectorOptions getInjectorOptions() {
-      return options;
+    Stage getStage() {
+      return options.stage;
     }
 
     /** Synchronize on this before calling {@link #build}. */
@@ -119,23 +121,31 @@
      */
     List<InjectorShell> build(BindingProcessor bindingProcessor,
         Stopwatch stopwatch, Errors errors) {
-      checkState(options != null, "Options not initialized");
-      checkState(options.stage != null, "Stage not initialized");
+      checkState(stage != null, "Stage not initialized");
       checkState(privateElements == null || parent != null, "PrivateElements with no parent");
       checkState(state != null, "no state. Did you remember to lock() ?");
 
+      // bind Stage and Singleton if this is a top-level injector
+      if (parent == null) {
+        modules.add(0, new RootModule(stage));
+      }
+      elements.addAll(Elements.getElements(stage, modules));
+      
+      // Look for injector-changing options
+      InjectorOptionsProcessor optionsProcessor = new InjectorOptionsProcessor(errors);
+      optionsProcessor.process(null, elements);
+      options = optionsProcessor.getOptions(stage, options);
+      
       InjectorImpl injector = new InjectorImpl(parent, state, options);
       if (privateElements != null) {
         privateElements.initInjector(injector);
       }
 
-      // bind Stage and Singleton if this is a top-level injector
+      // add default type converters if this is a top-level injector
       if (parent == null) {
-        modules.add(0, new RootModule(options.stage));
         new TypeConverterBindingProcessor(errors).prepareBuiltInConverters(injector);
       }
 
-      elements.addAll(Elements.getElements(options.stage, modules));
       stopwatch.resetAndLog("Module execution");
 
       new MessageProcessor(errors).process(injector, elements);
@@ -166,7 +176,7 @@
       injectorShells.add(new InjectorShell(this, elements, injector));
 
       // recursively build child shells
-      PrivateElementProcessor processor = new PrivateElementProcessor(errors, options);
+      PrivateElementProcessor processor = new PrivateElementProcessor(errors);
       processor.process(injector, elements);
       for (Builder builder : processor.getInjectorShellBuilders()) {
         injectorShells.addAll(builder.build(bindingProcessor, stopwatch, errors));
diff --git a/core/src/com/google/inject/internal/InternalInjectorCreator.java b/core/src/com/google/inject/internal/InternalInjectorCreator.java
index 2dc101c..812062a 100644
--- a/core/src/com/google/inject/internal/InternalInjectorCreator.java
+++ b/core/src/com/google/inject/internal/InternalInjectorCreator.java
@@ -67,36 +67,23 @@
   private final InjectorShell.Builder shellBuilder = new InjectorShell.Builder();
   private List<InjectorShell> shells;
   
-  public static class InjectorOptions {
-    final Stage stage;
-    final boolean jitDisabled;
-    final boolean allowCircularProxy;
-    
-    public InjectorOptions(Stage stage, boolean jitDisabled, boolean allowCircularProxy) {
-      this.stage = stage;
-      this.jitDisabled = jitDisabled;
-      this.allowCircularProxy = allowCircularProxy;
-    }
-  }
-
   public InternalInjectorCreator() {
     injectionRequestProcessor = new InjectionRequestProcessor(errors, initializer);
     bindingProcesor = new BindingProcessor(errors, initializer);
   }
   
-  public InternalInjectorCreator injectorOptions(InjectorOptions options) {
-    shellBuilder.setInjectorOptions(options);
+  public InternalInjectorCreator stage(Stage stage) {
+    shellBuilder.stage(stage);
     return this;
-  }  
+  }
 
   /**
-   * Sets the parent of the injector to-be-constructed.As a side effect, this sets this injector's
+   * Sets the parent of the injector to-be-constructed. As a side effect, this sets this injector's
    * stage to the stage of {@code parent} and sets {@link #requireExplicitBindings()} if the parent
    * injector also required them.
    */
   public InternalInjectorCreator parentInjector(InjectorImpl parent) {
     shellBuilder.parent(parent);
-    shellBuilder.setInjectorOptions(parent.options);
     return this;
   }
 
@@ -121,7 +108,7 @@
 
     injectDynamically();
 
-    if (shellBuilder.getInjectorOptions().stage == Stage.TOOL) {
+    if (shellBuilder.getStage() == Stage.TOOL) {
       // wrap the primaryInjector in a ToolStageInjector
       // to prevent non-tool-friendy methods from being called.
       return new ToolStageInjector(primaryInjector());
@@ -187,9 +174,9 @@
     stopwatch.resetAndLog("Instance injection");
     errors.throwCreationExceptionIfErrorsExist();
 
-    if(shellBuilder.getInjectorOptions().stage != Stage.TOOL) {
+    if(shellBuilder.getStage() != Stage.TOOL) {
       for (InjectorShell shell : shells) {
-        loadEagerSingletons(shell.getInjector(), shellBuilder.getInjectorOptions().stage, errors);
+        loadEagerSingletons(shell.getInjector(), shellBuilder.getStage(), errors);
       }
       stopwatch.resetAndLog("Preloading singletons");
     }
diff --git a/core/src/com/google/inject/internal/PrivateElementProcessor.java b/core/src/com/google/inject/internal/PrivateElementProcessor.java
index 086488e..9494856 100644
--- a/core/src/com/google/inject/internal/PrivateElementProcessor.java
+++ b/core/src/com/google/inject/internal/PrivateElementProcessor.java
@@ -16,7 +16,6 @@
 
 package com.google.inject.internal;
 
-import com.google.inject.internal.InternalInjectorCreator.InjectorOptions;
 import com.google.inject.internal.util.Lists;
 import com.google.inject.spi.PrivateElements;
 import java.util.List;
@@ -28,18 +27,15 @@
  */
 final class PrivateElementProcessor extends AbstractProcessor {
 
-  private final InjectorOptions options;
   private final List<InjectorShell.Builder> injectorShellBuilders = Lists.newArrayList();
 
-  PrivateElementProcessor(Errors errors, InjectorOptions options) {
+  PrivateElementProcessor(Errors errors) {
     super(errors);
-    this.options = options;
   }
 
   @Override public Boolean visit(PrivateElements privateElements) {
     InjectorShell.Builder builder = new InjectorShell.Builder()
         .parent(injector)
-        .setInjectorOptions(options)
         .privateElements(privateElements);
     injectorShellBuilders.add(builder);
     return true;
diff --git a/core/src/com/google/inject/spi/DefaultElementVisitor.java b/core/src/com/google/inject/spi/DefaultElementVisitor.java
index f6f8aa9..48fb06b 100644
--- a/core/src/com/google/inject/spi/DefaultElementVisitor.java
+++ b/core/src/com/google/inject/spi/DefaultElementVisitor.java
@@ -82,4 +82,12 @@
   public V visit(TypeListenerBinding binding) {
     return visitOther(binding);
   }
+  
+  public V visit(DisableCircularProxiesOption option) {
+    return visitOther(option);
+  }
+  
+  public V visit(RequireExplicitBindingsOption option) {
+    return visitOther(option);
+  }
 }
diff --git a/core/src/com/google/inject/spi/DisableCircularProxiesOption.java b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
new file mode 100644
index 0000000..67c4bf2
--- /dev/null
+++ b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
@@ -0,0 +1,46 @@
+/**

+ * Copyright (C) 2010 Google Inc.

+ *

+ * 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 com.google.inject.spi;

+

+import com.google.inject.Binder;

+import static com.google.inject.internal.util.Preconditions.checkNotNull;

+

+/**

+ * A request to disable circular proxies.

+ *

+ * @author sameb@google.com (Sam Berlin)

+ * @since 3.0

+ */

+public final class DisableCircularProxiesOption implements Element {

+  private final Object source;

+

+  DisableCircularProxiesOption(Object source) {

+    this.source = checkNotNull(source, "source");

+  }

+

+  public Object getSource() {

+    return source;

+  }

+

+  public void applyTo(Binder binder) {

+    binder.withSource(getSource()).disableCircularProxies();

+  }

+

+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {

+    return visitor.visit(this);

+  }

+}

diff --git a/core/src/com/google/inject/spi/ElementVisitor.java b/core/src/com/google/inject/spi/ElementVisitor.java
index 20f901c..517b1a0 100644
--- a/core/src/com/google/inject/spi/ElementVisitor.java
+++ b/core/src/com/google/inject/spi/ElementVisitor.java
@@ -86,4 +86,18 @@
    * Visit an injectable type listener binding.
    */
   V visit(TypeListenerBinding binding);
+  
+  /**
+   * Visit a require explicit bindings command.
+   * 
+   * @since 3.0
+   */
+  V visit(RequireExplicitBindingsOption option);
+  
+  /**
+   * Visit a disable circular proxies command.
+   * 
+   * @since 3.0
+   */
+  V visit(DisableCircularProxiesOption option);
 }
diff --git a/core/src/com/google/inject/spi/Elements.java b/core/src/com/google/inject/spi/Elements.java
index 75795b4..6cbe2a8 100644
--- a/core/src/com/google/inject/spi/Elements.java
+++ b/core/src/com/google/inject/spi/Elements.java
@@ -300,6 +300,14 @@
       elements.add(privateElements);
       return new RecordingBinder(this, privateElements);
     }
+    
+    public void disableCircularProxies() {
+      elements.add(new DisableCircularProxiesOption(getSource()));
+    }
+    
+    public void requireExplicitBindings() {
+      elements.add(new RequireExplicitBindingsOption(getSource()));     
+    }
 
     public void expose(Key<?> key) {
       exposeInternal(key);
diff --git a/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
new file mode 100644
index 0000000..4515bd4
--- /dev/null
+++ b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
@@ -0,0 +1,46 @@
+/**

+ * Copyright (C) 2010 Google Inc.

+ *

+ * 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 com.google.inject.spi;

+

+import com.google.inject.Binder;

+import static com.google.inject.internal.util.Preconditions.checkNotNull;

+

+/**

+ * A request to require explicit bindings.

+ *

+ * @author sameb@google.com (Sam Berlin)

+ * @since 3.0

+ */

+public final class RequireExplicitBindingsOption implements Element {

+  private final Object source;

+

+  RequireExplicitBindingsOption(Object source) {

+    this.source = checkNotNull(source, "source");

+  }

+

+  public Object getSource() {

+    return source;

+  }

+

+  public void applyTo(Binder binder) {

+    binder.withSource(getSource()).requireExplicitBindings();

+  }

+

+  public <T> T acceptVisitor(ElementVisitor<T> visitor) {

+    return visitor.visit(this);

+  }

+}

diff --git a/core/test/com/google/inject/CircularDependencyTest.java b/core/test/com/google/inject/CircularDependencyTest.java
index 1cc4e74..428acde 100644
--- a/core/test/com/google/inject/CircularDependencyTest.java
+++ b/core/test/com/google/inject/CircularDependencyTest.java
@@ -106,14 +106,13 @@
   }
   
   public void testDisablingCircularProxies() {
-    Injector injector = new InjectorBuilder()
-      .disableCircularProxies()
-      .addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       protected void configure() {
+        binder().disableCircularProxies();
         binder.bind(A.class).to(E.class);
         binder.bind(B.class).to(E.class);
       }
-    }).build();
+    });
     
     try {
       injector.getInstance(A.class);
diff --git a/core/test/com/google/inject/JitBindingsTest.java b/core/test/com/google/inject/JitBindingsTest.java
index ccf1516..ea684a4 100644
--- a/core/test/com/google/inject/JitBindingsTest.java
+++ b/core/test/com/google/inject/JitBindingsTest.java
@@ -1,6 +1,9 @@
 package com.google.inject;
 
 import static com.google.inject.Asserts.assertContains;
+import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING_PROVIDER;
+import static com.google.inject.JitBindingsTest.GetBindingCheck.FAIL_ALL;
+import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING;
 import static com.google.inject.internal.util.ImmutableSet.of;
 
 import junit.framework.TestCase;
@@ -8,7 +11,7 @@
 import java.util.Set;
 
 /**
- * Some tests for {@link InjectorBuilder#requireExplicitBindings()}
+ * Some tests for {@link Binder#requireExplicitBindings()}
  * 
  * @author sberlin@gmail.com (Sam Berlin)
  */
@@ -23,110 +26,117 @@
   }
   
   public void testLinkedBindingWorks() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(Foo.class).to(FooImpl.class);
       }
-    }).build();
+    });
     // Foo was explicitly bound
     ensureWorks(injector, Foo.class);
     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
     // It is OK to call getBinding for introspection, but an error to get the provider
     // of the binding
-    ensureFails(injector, true, FooImpl.class);
+    ensureFails(injector, ALLOW_BINDING, FooImpl.class);
   }
   
   public void testMoreBasicsWork() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(Foo.class).to(FooImpl.class);
         bind(Bar.class);
         bind(FooBar.class);
       }
-    }).build();
+    });
     // Foo, Bar & FooBar was explicitly bound    
     ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
     // It is OK to call getBinding for introspection, but an error to get the provider
     // of the binding    
-    ensureFails(injector, true,  FooImpl.class);    
+    ensureFails(injector, ALLOW_BINDING,  FooImpl.class);    
   }
   
   public void testLinkedEagerSingleton() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(Foo.class).to(FooImpl.class).asEagerSingleton();
       }
-    }).build();
+    });
     // Foo was explicitly bound
     ensureWorks(injector, Foo.class);
     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
     // It is OK to call getBinding for introspection, but an error to get the provider
     // of the binding
-    ensureFails(injector, true, FooImpl.class);
+    ensureFails(injector, ALLOW_BINDING, FooImpl.class);
   }
   
   public void testBasicsWithEagerSingleton() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(Foo.class).to(FooImpl.class).asEagerSingleton();
         bind(Bar.class);
         bind(FooBar.class);
       }
-    }).build();
+    });
     // Foo, Bar & FooBar was explicitly bound    
     ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
     // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
     // It is OK to call getBinding for introspection, but an error to get the provider
     // of the binding    
-    ensureFails(injector, true,  FooImpl.class);    
+    ensureFails(injector, ALLOW_BINDING,  FooImpl.class);    
   }  
   
   public void testLinkedToScoped() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder.requireExplicitBindings();
         bind(Foo.class).to(ScopedFooImpl.class);
       }
-    }).build();
+    });
     // Foo was explicitly bound
     ensureWorks(injector, Foo.class);
     // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
     // It is OK to call getBinding for introspection, but an error to get the provider
     // of the binding
-    ensureFails(injector, true, ScopedFooImpl.class);    
+    ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class);    
   }
   
   public void testBasicsWithScoped() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(Foo.class).to(ScopedFooImpl.class);
         bind(Bar.class);
         bind(FooBar.class);
       }
-    }).build();
+    });
     // Foo, Bar & FooBar was explicitly bound    
     ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
     // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
     // It is OK to call getBinding for introspection, but an error to get the provider
     // of the binding    
-    ensureFails(injector, true,  ScopedFooImpl.class);   
+    ensureFails(injector, ALLOW_BINDING,  ScopedFooImpl.class);   
   }
   
   public void testFailsIfInjectingScopedDirectlyWhenItIsntBound() {
     try {
-      new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+      Guice.createInjector(new AbstractModule() {
         @Override
         protected void configure() {
+          binder().requireExplicitBindings();
           bind(Foo.class).to(ScopedFooImpl.class);
           bind(WantsScopedFooImpl.class);
         }
-      }).build();
+      });
       fail();
     } catch(CreationException expected) {
       assertContains(expected.getMessage(), "1) " + jitFailed(ScopedFooImpl.class));
@@ -135,22 +145,28 @@
   }
   
   public void testLinkedProviderBindingWorks() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(Foo.class).toProvider(FooProvider.class);
       }
-    }).build();
+    });
     // Foo was explicitly bound
     ensureWorks(injector, Foo.class);
     // FooImpl was not bound at all (even implicitly), it is an error
     // to call getInstance, getProvider, or getBinding.
-    ensureFails(injector, false, FooImpl.class);
+    ensureFails(injector, FAIL_ALL, FooImpl.class);
   }
   
   public void testJitGetFails() {
     try {
-      new InjectorBuilder().requireExplicitBindings().build().getInstance(Bar.class);
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+         binder().requireExplicitBindings(); 
+        }
+      }).getInstance(Bar.class);
       fail("should have failed");
     } catch(ConfigurationException expected) {
       assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
@@ -160,13 +176,14 @@
   
   public void testJitInjectionFails() {
     try {
-      new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+      Guice.createInjector(new AbstractModule() {
         @Override
         protected void configure() {
+          binder().requireExplicitBindings();
           bind(Foo.class).to(FooImpl.class);
           bind(FooBar.class);
         }
-      }).build();
+      });
       fail("should have failed");
     } catch (CreationException expected) {
       assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
@@ -176,7 +193,12 @@
 
   public void testJitProviderGetFails() {
     try {
-      new InjectorBuilder().requireExplicitBindings().build().getProvider(Bar.class);
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExplicitBindings(); 
+        }
+      }).getProvider(Bar.class);
       fail("should have failed");
     } catch (ConfigurationException expected) {
       assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
@@ -186,13 +208,14 @@
 
   public void testJitProviderInjectionFails() {
     try {
-      new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+      Guice.createInjector(new AbstractModule() {
         @Override
         protected void configure() {
+          binder().requireExplicitBindings();
           bind(Foo.class).to(FooImpl.class);
           bind(ProviderFooBar.class);
         }
-      }).build();
+      });
       fail("should have failed");
     } catch (CreationException expected) {
       assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
@@ -201,55 +224,61 @@
   }
   
   public void testImplementedBy() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(ImplBy.class);
       }
-    }).build();
+    });
     ensureWorks(injector, ImplBy.class);
-    ensureFails(injector, true, ImplByImpl.class);
+    ensureFails(injector, ALLOW_BINDING, ImplByImpl.class);
   }
   
   public void testImplementedBySomethingThatIsAnnotated() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(ImplByScoped.class);
       }
-    }).build();
+    });
     ensureWorks(injector, ImplByScoped.class);
-    ensureFails(injector, true, ImplByScopedImpl.class);    
+    ensureFails(injector, ALLOW_BINDING, ImplByScopedImpl.class);    
   }
   
   public void testProvidedBy() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(ProvBy.class);
       }
-    }).build();
+    });
     ensureWorks(injector, ProvBy.class);
-    ensureFails(injector, true, ProvByProvider.class);
+    ensureFails(injector, ALLOW_BINDING, ProvByProvider.class);
   }
   
   public void testProviderMethods() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
-      @Override protected void configure() {}
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        binder().requireExplicitBindings();
+      }
       @SuppressWarnings("unused") @Provides Foo foo() { return new FooImpl(); }
-    }).build();
+    });
     ensureWorks(injector, Foo.class);
   }
   
-  public void testChildInjectors() {
-    Injector parent = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+  public void testChildInjectorInheritsOption() {
+    Injector parent = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {
+        binder().requireExplicitBindings();
         bind(Bar.class);
       }
-    }).build();
+    });
     ensureWorks(parent, Bar.class);
-    ensureFails(parent, false, FooImpl.class, FooBar.class, Foo.class);
+    ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class);
     
     try {
       parent.createChildInjector(new AbstractModule() {
@@ -271,8 +300,8 @@
       }
     });
     ensureWorks(child, Foo.class, Bar.class);
-    ensureFails(child, true, FooImpl.class);
-    ensureFails(parent, false, FooImpl.class, FooBar.class, Foo.class); // parent still doesn't have these
+    ensureFails(child, ALLOW_BINDING, FooImpl.class);
+    ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class); // parent still doesn't have these
     
     Injector grandchild = child.createChildInjector(new AbstractModule() {
       @Override
@@ -281,15 +310,83 @@
       }
     });
     ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
-    ensureFails(grandchild, true, FooImpl.class);
-    ensureFails(child, true, FooImpl.class);
-    ensureFails(parent, false, FooImpl.class, FooBar.class, Foo.class); // parent still doesn't have these    
+    ensureFails(grandchild, ALLOW_BINDING, FooImpl.class);
+    ensureFails(child, ALLOW_BINDING, FooImpl.class);
+    ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class); // parent still doesn't have these    
+  }
+  
+  public void testChildInjectorAddsOption() {
+    Injector parent = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(Bar.class);
+      }
+    });
+    int totalParentBindings = parent.getAllBindings().size();
+    
+    try {
+      parent.createChildInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          binder().requireExplicitBindings();
+          bind(FooBar.class);
+        }
+      });
+      fail("should have failed");
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(), "1) " + jitFailed(Foo.class));
+      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
+    }
+    assertEquals(totalParentBindings, parent.getAllBindings().size());
+    
+    Injector child = parent.createChildInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        binder().requireExplicitBindings();
+        bind(Foo.class).to(FooImpl.class);
+      }
+    });
+    totalParentBindings++; // creating this child added FooImpl to the parent.
+    assertEquals(totalParentBindings, parent.getAllBindings().size());
+    ensureWorks(child, Foo.class, Bar.class);
+    ensureFails(child, ALLOW_BINDING_PROVIDER, FooImpl.class);
+    // Make extra certain that if something tries to inject a FooImpl from child
+    // that it fails, even if calling getBinding().getProvider works.. because
+    // the binding is built with the parent injector.
+    try {
+      child.injectMembers(new Object() {
+        @SuppressWarnings("unused")
+        @Inject
+        void inject(FooImpl fooImpl) {}
+      });
+      fail();
+    } catch(ConfigurationException expected) {
+      assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class));
+      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
+    }
+    
+    Injector grandchild = child.createChildInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(FooBar.class);
+      }
+    });
+    assertEquals(totalParentBindings, parent.getAllBindings().size());    
+    ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
+    ensureFails(grandchild, ALLOW_BINDING_PROVIDER, FooImpl.class);
+    ensureFails(child, ALLOW_BINDING_PROVIDER, FooImpl.class);
+    
+    // Make sure siblings of children don't inherit each others settings...
+    // a new child should be able to get FooImpl.
+    child = parent.createChildInjector();
+    ensureWorks(child, FooImpl.class);
   }
 
-  public void testPrivateModules() {
+  public void testPrivateModulesInheritOptions() {
     try {
-      new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+      Guice.createInjector(new AbstractModule() {
         protected void configure() {
+          binder().requireExplicitBindings();
           bind(Foo.class).to(FooImpl.class);
   
           install(new PrivateModule() {
@@ -299,7 +396,7 @@
             }
           });
         }
-      }).build();
+      });
       fail("should have failed");
     } catch(CreationException expected) {
       assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
@@ -307,16 +404,62 @@
     }
   }
   
+  public void testPrivateModuleAddsOption() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(Foo.class).to(FooImpl.class);
+  
+          // Fails because FooBar is in the private module,
+          // and it wants Bar, but Bar would be JIT.
+          install(new PrivateModule() {
+            public void configure() {
+              binder().requireExplicitBindings();
+              bind(FooBar.class);
+              expose(FooBar.class);
+            }
+          });
+        }
+      });
+      fail("should have failed");
+    } catch(CreationException expected) {
+      assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
+      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
+    }
+  }
+
+  public void testPrivateModuleSiblingsDontShareOption() {
+    Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(Foo.class).to(FooImpl.class);
+
+        install(new PrivateModule() {
+          public void configure() {
+            binder().requireExplicitBindings();
+          }
+        });
+
+        // This works, even though Bar is JIT,
+        // because the requireExplicitBindings isn't shared
+        // between sibling private modules.
+        install(new PrivateModule() {
+          public void configure() {
+            bind(FooBar.class);
+            expose(FooBar.class);
+          }
+        });
+      }
+    });
+  }  
+
   public void testTypeLiteralsCanBeInjected() {
-    Injector injector = new InjectorBuilder()
-      .requireExplicitBindings()
-      .addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
         @Override protected void configure() {
+          binder().requireExplicitBindings();
           bind(new TypeLiteral<WantsTypeLiterals<String>>() {});
           bind(new TypeLiteral<Set<String>>() {}).toInstance(of("bar"));
         }
-      })
-      .build();
+      });
 
     WantsTypeLiterals<String> foo = injector.getInstance(new Key<WantsTypeLiterals<String>>() {});
     assertEquals(foo.literal.getRawType(), String.class);
@@ -324,10 +467,9 @@
   }
   
   public void testMembersInjectorsCanBeInjected() {
-    Injector injector = new InjectorBuilder()
-    .requireExplicitBindings()
-    .addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
       @Override protected void configure() {
+        binder().requireExplicitBindings();
       }
       
       @Provides String data(MembersInjector<String> mi) {
@@ -335,8 +477,7 @@
         mi.injectMembers(data);
         return data;
       }
-    })
-    .build();
+    });
 
     String data = injector.getInstance(String.class);
     assertEquals("foo", data);
@@ -350,11 +491,12 @@
     }
   }
   
-  private void ensureFails(Injector injector, boolean allowGetBinding, Class<?>... classes) {
+  enum GetBindingCheck { FAIL_ALL, ALLOW_BINDING, ALLOW_BINDING_PROVIDER }
+  private void ensureFails(Injector injector, GetBindingCheck getBinding, Class<?>... classes) {
     for(int i = 0; i < classes.length; i++) {      
       try { 
         injector.getInstance(classes[i]);
-        fail("should have failed");
+        fail("should have failed tring to retrieve class: " + classes[i]);
       } catch(ConfigurationException expected) {
         assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
         assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
@@ -362,25 +504,31 @@
       
       try { 
         injector.getProvider(classes[i]);
-        fail("should have failed");
+        fail("should have failed tring to retrieve class: " + classes[i]);
       } catch(ConfigurationException expected) {
         assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
         assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
       }
       
-      if(allowGetBinding) {
+      if (getBinding == GetBindingCheck.ALLOW_BINDING
+          || getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
         Binding<?> binding = injector.getBinding(classes[i]);
         try {
           binding.getProvider();
-          fail("should have failed");
+          if (getBinding != GetBindingCheck.ALLOW_BINDING_PROVIDER) {
+            fail("should have failed trying to retrieve class: " + classes[i]);
+          }
         } catch(ConfigurationException expected) {
+          if (getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
+            throw expected;
+          }
           assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
           assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
         }
       } else {
         try {
           injector.getBinding(classes[i]);
-          fail("should have failed");          
+          fail("should have failed tring to retrieve class: " + classes[i]);          
         } catch(ConfigurationException expected) {
           assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
           assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
index b133fb8..cb3fd51 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
@@ -32,7 +32,6 @@
 import com.google.inject.CreationException;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.InjectorBuilder;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.Provider;
@@ -41,7 +40,6 @@
 import com.google.inject.TypeLiteral;
 import com.google.inject.internal.util.ImmutableSet;
 import com.google.inject.internal.util.Maps;
-import com.google.inject.multibindings.SpiUtils.VisitType;
 import com.google.inject.name.Names;
 import com.google.inject.spi.Dependency;
 import com.google.inject.spi.HasDependencies;
@@ -488,9 +486,7 @@
 
   /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */
   public void testMultibinderDependenciesInToolStage() {
-    Injector injector = new InjectorBuilder()
-      .stage(Stage.TOOL)
-      .addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() {
         protected void configure() {
           MapBinder<Integer, String> mapBinder
               = MapBinder.newMapBinder(binder(), Integer.class, String.class);
@@ -498,8 +494,7 @@
           mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b")));
   
           bindConstant().annotatedWith(Names.named("b")).to("B");
-        }})
-      .build();
+        }});
 
     Binding<Map<Integer, String>> binding = injector.getBinding(new Key<Map<Integer, String>>() {});
     HasDependencies withDependencies = (HasDependencies) binding;
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
index bbfa28e..b4d4046 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
@@ -45,7 +45,6 @@
 import com.google.inject.CreationException;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.InjectorBuilder;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.Provider;
@@ -400,17 +399,14 @@
    * really care about the underlying structure of those bindings, which are implementation details.
    */
   public void testMultibinderDependenciesInToolStage() {
-    Injector injector = new InjectorBuilder()
-      .stage(Stage.TOOL)
-      .addModules(new AbstractModule() {
+    Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() {
         protected void configure() {
           Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
           multibinder.addBinding().toInstance("A");
           multibinder.addBinding().to(Key.get(String.class, Names.named("b")));
   
           bindConstant().annotatedWith(Names.named("b")).to("B");
-        }})
-      .build();
+        }});
 
     Binding<Set<String>> binding = injector.getBinding(new Key<Set<String>>() {});
     HasDependencies withDependencies = (HasDependencies) binding;
diff --git a/extensions/persist/test/com/google/inject/persist/EdslTest.java b/extensions/persist/test/com/google/inject/persist/EdslTest.java
index b1d4b0e..078ef17 100644
--- a/extensions/persist/test/com/google/inject/persist/EdslTest.java
+++ b/extensions/persist/test/com/google/inject/persist/EdslTest.java
@@ -1,6 +1,7 @@
 package com.google.inject.persist;
 
-import com.google.inject.InjectorBuilder;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
 import com.google.inject.Stage;
 import com.google.inject.persist.jpa.JpaPersistModule;
 import junit.framework.TestCase;
@@ -11,10 +12,12 @@
 public class EdslTest extends TestCase {
 
   public void testModuleConfigUsingJpa() throws Exception {
-    new InjectorBuilder()
-        .addModules(new JpaPersistModule("myunit"))
-        .stage(Stage.PRODUCTION)
-        .requireExplicitBindings()
-        .build();
+    Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
+      @Override
+      protected void configure() {
+        install(new JpaPersistModule("myunit"));
+        binder().requireExplicitBindings();
+      };
+    });
   }
 }
diff --git a/extensions/servlet/test/com/google/inject/servlet/EdslTest.java b/extensions/servlet/test/com/google/inject/servlet/EdslTest.java
index 9774a3d..47d1400 100644
--- a/extensions/servlet/test/com/google/inject/servlet/EdslTest.java
+++ b/extensions/servlet/test/com/google/inject/servlet/EdslTest.java
@@ -15,9 +15,9 @@
  */
 package com.google.inject.servlet;
 
+import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.InjectorBuilder;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.Singleton;
@@ -33,13 +33,18 @@
 public class EdslTest extends TestCase {
 
   public final void testExplicitBindingsWorksWithGuiceServlet() {
-    Injector injector = new InjectorBuilder().requireExplicitBindings()
-        .addModules(new ServletModule() {
+    Injector injector = Guice.createInjector(
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            binder().requireExplicitBindings();
+          }
+        }, new ServletModule() {
           @Override protected void configureServlets() {
             bind(DummyServlet.class).in(Singleton.class);
             serve("/*").with(DummyServlet.class);
           }
-        }).build();
+        });
 
     assertNotNull(injector.getInstance(DummyServlet.class));
   }