Moved name-related logic into a subpackage.

git-svn-id: https://google-guice.googlecode.com/svn/trunk@143 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/guice.ipr b/guice.ipr
index ccd1b86..653cae8 100644
--- a/guice.ipr
+++ b/guice.ipr
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project version="4" relativePaths="true">
+<project version="4" relativePaths="false">
   <component name="AntConfiguration">
     <defaultAnt bundledAnt="true" />
     <buildFile url="file://$PROJECT_DIR$/build.xml">
@@ -15,7 +15,7 @@
       <class-settings class="com.google.devtools.intellig.configcheck.ProjectPathChecker" />
       <class-settings class="com.google.devtools.intellig.configcheck.PythonSdkChecker" />
       <class-settings class="com.google.devtools.intellig.configcheck.ProjectJdkChecker">
-        <setting name="getProjectJdk" value="$PROJECT_DIR$/../../buildtools/java/jdk1.5.0_06" />
+        <setting name="getProjectJdk" value="/Users/crazybob/buildtools/java/jdk1.5.0_06" />
         <setting name="getModuleJdks" value="rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAABA/QAAAAAAAAHg=" />
       </class-settings>
       <class-settings class="com.google.devtools.intellig.configcheck.ClearOutputChecker" />
diff --git a/src/com/google/inject/AbstractModule.java b/src/com/google/inject/AbstractModule.java
index 8251ac1..a9c9209 100644
--- a/src/com/google/inject/AbstractModule.java
+++ b/src/com/google/inject/AbstractModule.java
@@ -19,6 +19,7 @@
 import com.google.inject.util.Objects;
 import java.util.Map;
 import java.util.Properties;
+import java.lang.annotation.Annotation;
 
 /**
  * A support class for {@link Module Modules} which reduces repetition and
@@ -87,7 +88,8 @@
   /**
    * @see ContainerBuilder#bind(TypeLiteral)
    */
-  protected <T> ContainerBuilder.BindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
+  protected <T> ContainerBuilder.BindingBuilder<T> bind(
+      TypeLiteral<T> typeLiteral) {
     return builder.bind(typeLiteral);
   }
 
@@ -106,31 +108,19 @@
   }
 
   /**
-   * @see ContainerBuilder#bind(String)
+   * @see ContainerBuilder#bindConstant(Class)
    */
-  protected ContainerBuilder.ConstantBindingBuilder bind(String name) {
-    return builder.bind(name);
+  protected ContainerBuilder.ConstantBindingBuilder bindConstant(
+      Class<? extends Annotation> annotationType) {
+    return builder.bindConstant(annotationType);
   }
 
   /**
-   * @see ContainerBuilder#bindProperties(java.util.Map)
+   * @see ContainerBuilder#bindConstant(java.lang.annotation.Annotation)
    */
-  protected void bindProperties(Map<String, String> properties) {
-    builder.bindProperties(properties);
-  }
-
-  /**
-   * @see ContainerBuilder#bindProperties(java.util.Properties)
-   */
-  protected void bindProperties(Properties properties) {
-    builder.bindProperties(properties);
-  }
-
-  /**
-   * @see ContainerBuilder#requestStaticInjection(Class[])
-   */
-  protected void requestStaticInjection(Class<?>... types) {
-    builder.requestStaticInjection(types);
+  protected ContainerBuilder.ConstantBindingBuilder bindConstant(
+      Annotation annotation) {
+    return builder.bindConstant(annotation);
   }
 
   /**
@@ -139,4 +129,11 @@
   protected void install(Module module) {
     builder.install(module);
   }
+
+  /**
+   * @see ContainerBuilder#requestStaticInjection(Class[])
+   */
+  protected void requestStaticInjection(Class<?>... types) {
+    builder.requestStaticInjection(types);
+  }
 }
diff --git a/src/com/google/inject/ContainerBuilder.java b/src/com/google/inject/ContainerBuilder.java
index 7dbff74..18e7646 100644
--- a/src/com/google/inject/ContainerBuilder.java
+++ b/src/com/google/inject/ContainerBuilder.java
@@ -192,17 +192,9 @@
   }
 
   /**
-   * Binds a constant to the given name.
-   */
-  public ConstantBindingBuilder bind(String name) {
-    ensureNotCreated();
-    return bind(source(), Key.strategyFor(new NamedImpl(name)));
-  }
-
-  /**
    * Binds a constant to the given annotation.
    */
-  public ConstantBindingBuilder bind(Annotation annotation) {
+  public ConstantBindingBuilder bindConstant(Annotation annotation) {
     ensureNotCreated();
     return bind(source(), Key.strategyFor(annotation));
   }
@@ -210,7 +202,7 @@
   /**
    * Binds a constant to the given annotation type.
    */
-  public ConstantBindingBuilder bind(
+  public ConstantBindingBuilder bindConstant(
       Class<? extends Annotation> annotationType) {
     ensureNotCreated();
     return bind(source(), Key.strategyFor(annotationType));
@@ -228,32 +220,6 @@
   }
 
   /**
-   * Binds a string constant for each property.
-   */
-  public void bindProperties(Map<String, String> properties) {
-    ensureNotCreated();
-    Object source = source();
-    for (Map.Entry<String, String> entry : properties.entrySet()) {
-      String key = entry.getKey();
-      String value = entry.getValue();
-      bind(source, Key.strategyFor(new NamedImpl(key))).to(value);
-    }
-  }
-
-  /**
-   * Binds a string constant for each property.
-   */
-  public void bindProperties(Properties properties) {
-    ensureNotCreated();
-    Object source = source();
-    for (Map.Entry<Object, Object> entry : properties.entrySet()) {
-      String key = (String) entry.getKey();
-      String value = (String) entry.getValue();
-      bind(source, Key.strategyFor(new NamedImpl(key))).to(value);
-    }
-  }
-
-  /**
    * Upon successful creation, the {@link Container} will inject static fields
    * and methods in the given classes.
    *
@@ -512,13 +478,6 @@
     }
 
     /**
-     * Binds to injection points annotated with {@code @Named(name)}.
-     */
-    public BindingBuilder<T> named(String name) {
-      return annotatedWith(new NamedImpl(nonNull(name, "name")));
-    }
-
-    /**
      * Specifies the annotation type for this binding.
      */
     public BindingBuilder<T> annotatedWith(
diff --git a/src/com/google/inject/Key.java b/src/com/google/inject/Key.java
index afcd968..ed993f6 100644
--- a/src/com/google/inject/Key.java
+++ b/src/com/google/inject/Key.java
@@ -95,26 +95,6 @@
    * parameter in the anonymous class's type hierarchy so we can reconstitute it
    * at runtime despite erasure.
    *
-   * <p>Example usage for a binding of type {@code Foo} annotated with
-   * {@code @Named("bar")}:
-   *
-   * <p>{@code new Key<Foo>("bar") {}}.
-   */
-  @SuppressWarnings("unchecked")
-  protected Key(String name) {
-    this.annotationStrategy = strategyFor(new NamedImpl(name));
-    this.typeLiteral
-        = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass());
-    this.hashCode = computeHashCode();
-  }
-
-  /**
-   * Constructs a new key. Derives the type from this class's type parameter.
-   *
-   * <p>Clients create an empty anonymous subclass. Doing so embeds the type
-   * parameter in the anonymous class's type hierarchy so we can reconstitute it
-   * at runtime despite erasure.
-   *
    * <p>Example usage for a binding of type {@code Foo}:
    *
    * <p>{@code new Key<Foo>() {}}.
@@ -227,13 +207,6 @@
   }
 
   /**
-   * Gets a key for an injection type and the annotation {@code Named(name)}.
-   */
-  public static <T> Key<T> get(Class<T> type, String name) {
-    return new SimpleKey<T>(type, strategyFor(new NamedImpl(name)));
-  }
-
-  /**
    * Gets a key for an injection type and an annotation.
    */
   public static <T> Key<T> get(Class<T> type, Annotation annotation) {
@@ -263,13 +236,6 @@
   }
 
   /**
-   * Gets a key for an injection type and the annotation {@code Named(name)}.
-   */
-  public static Key<?> get(Type type, String name) {
-    return new SimpleKey<Object>(type, strategyFor(new NamedImpl(name)));
-  }
-
-  /**
    * Gets a key for an injection type.
    */
   public static <T> Key<T> get(TypeLiteral<T> typeLiteral) {
@@ -293,13 +259,6 @@
   }
 
   /**
-   * Gets a key for an injection type and the annotation {@code Named(name)}.
-   */
-  public static <T> Key<T> get(TypeLiteral<T> typeLiteral, String name) {
-    return new SimpleKey<T>(typeLiteral, strategyFor(new NamedImpl(name)));
-  }
-
-  /**
    * Gets a key for the given type, member and annotations.
    */
   static Key<?> get(Type type, Member member, Annotation[] annotations,
diff --git a/src/com/google/inject/Named.java b/src/com/google/inject/name/Named.java
similarity index 92%
rename from src/com/google/inject/Named.java
rename to src/com/google/inject/name/Named.java
index 0a0bd8d..5691814 100644
--- a/src/com/google/inject/Named.java
+++ b/src/com/google/inject/name/Named.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.google.inject;
+package com.google.inject.name;
 
 import java.lang.annotation.Retention;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import com.google.inject.ForBinding;
 
 /**
  * Annotates named things.
diff --git a/src/com/google/inject/NamedImpl.java b/src/com/google/inject/name/NamedImpl.java
similarity index 94%
rename from src/com/google/inject/NamedImpl.java
rename to src/com/google/inject/name/NamedImpl.java
index c8be943..911b238 100644
--- a/src/com/google/inject/NamedImpl.java
+++ b/src/com/google/inject/name/NamedImpl.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.google.inject;
+package com.google.inject.name;
 
 import java.lang.annotation.Annotation;
 import com.google.inject.util.Objects;
+import com.google.inject.name.Named;
 
 class NamedImpl implements Named {
 
diff --git a/src/com/google/inject/name/Names.java b/src/com/google/inject/name/Names.java
new file mode 100644
index 0000000..ed074f0
--- /dev/null
+++ b/src/com/google/inject/name/Names.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2006 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.name;
+
+import java.util.Map;
+import java.util.Properties;
+import com.google.inject.Key;
+import com.google.inject.ContainerBuilder;
+import com.google.inject.spi.SourceProvider;
+import com.google.inject.spi.DefaultSourceProvider;
+
+/**
+ * Utility methods for use with {@code @}{@link Named}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class Names {
+
+  private Names() {}
+
+  /**
+   * Creates a {@link Named} annotation with {@code name} as the value.
+   */
+  public static Named annotationFor(String name) {
+    return new NamedImpl(name);
+  }
+
+  /**
+   * Binds a string constant for each property.
+   */
+  public static void bindProperties(ContainerBuilder builder,
+      Map<String, String> properties) {
+    skipNames(builder);
+    for (Map.Entry<String, String> entry : properties.entrySet()) {
+      String key = entry.getKey();
+      String value = entry.getValue();
+      builder.bind(Key.get(String.class, new NamedImpl(key))).to(value);
+    }
+  }
+
+  /**
+   * Binds a string constant for each property.
+   */
+  public static void bindProperties(ContainerBuilder builder,
+      Properties properties) {
+    skipNames(builder);
+    for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+      String key = (String) entry.getKey();
+      String value = (String) entry.getValue();
+      builder.bind(Key.get(String.class, new NamedImpl(key))).to(value);
+    }
+  }
+
+  private static void skipNames(ContainerBuilder builder) {
+    SourceProvider sourceProvider = builder.getSourceProvider();
+    if (sourceProvider instanceof DefaultSourceProvider) {
+      ((DefaultSourceProvider) sourceProvider).skip(Names.class);
+    }
+  }
+}
diff --git a/src/com/google/inject/Named.java b/src/com/google/inject/servlet/RequestParameters.java
similarity index 66%
copy from src/com/google/inject/Named.java
copy to src/com/google/inject/servlet/RequestParameters.java
index 0a0bd8d..403f6e6 100644
--- a/src/com/google/inject/Named.java
+++ b/src/com/google/inject/servlet/RequestParameters.java
@@ -14,18 +14,21 @@
  * limitations under the License.
  */
 
-package com.google.inject;
+package com.google.inject.servlet;
 
 import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import com.google.inject.ForBinding;
 
 /**
- * Annotates named things.
+ * Apply this to field or parameters of type {@code Map<String, String[]>}
+ * when you want the HTTP request parameter map to be injected.
  *
  * @author crazybob@google.com (Bob Lee)
  */
 @Retention(RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER })
 @ForBinding
-public @interface Named {
-  String value();
-}
+public @interface RequestParameters {}
diff --git a/src/com/google/inject/servlet/ServletModule.java b/src/com/google/inject/servlet/ServletModule.java
index fb07713..a71b842 100644
--- a/src/com/google/inject/servlet/ServletModule.java
+++ b/src/com/google/inject/servlet/ServletModule.java
@@ -40,12 +40,6 @@
  */
 public class ServletModule extends AbstractModule {
 
-  /**
-   * Name of the request parameters binding. The type is {@code
-   * Map<String, String[]>}.
-   */
-  public static final String REQUEST_PARAMETERS = "requestParameters";
-
   protected void configure() {
     // Scopes.
     scope(REQUEST_NAME, REQUEST);
@@ -80,7 +74,7 @@
 
     // Bind request parameters.
     bind(new TypeLiteral<Map<String, String[]>>() {})
-        .named(REQUEST_PARAMETERS)
+        .annotatedWith(RequestParameters.class)
         .to(new Factory<Map<String, String[]>>() {
           @SuppressWarnings({"unchecked"})
           public Map<String, String[]> get() {
diff --git a/test/com/google/inject/ConstantConversionTest.java b/test/com/google/inject/ConstantConversionTest.java
index 5792879..fdebfed 100644
--- a/test/com/google/inject/ConstantConversionTest.java
+++ b/test/com/google/inject/ConstantConversionTest.java
@@ -20,48 +20,56 @@
 
 import java.util.Map;
 import java.util.HashMap;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * @author crazybob@google.com (Bob Lee)
  */
 public class ConstantConversionTest extends TestCase {
 
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface NumericValue {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface BooleanValue {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface EnumValue {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface ClassName {}
+
   public static class Foo {
-    @Inject @Named("#") Integer integerField;
-    @Inject @Named("#") int primitiveIntField;
-    @Inject @Named("#") Long longField;
-    @Inject @Named("#") long primitiveLongField;
-    @Inject @Named("boolean") Boolean booleanField;
-    @Inject @Named("boolean") boolean primitiveBooleanField;
-    @Inject @Named("#") Byte byteField;
-    @Inject @Named("#") byte primitiveByteField;
-    @Inject @Named("#") Short shortField;
-    @Inject @Named("#") short primitiveShortField;
-    @Inject @Named("#") Float floatField;
-    @Inject @Named("#") float primitiveFloatField;
-    @Inject @Named("#") Double doubleField;
-    @Inject @Named("#") short primitiveDoubleField;
-    @Inject @Named("enum") Bar enumField;
-    @Inject @Named("class") Class<?> classField;
+    @Inject @NumericValue Integer integerField;
+    @Inject @NumericValue int primitiveIntField;
+    @Inject @NumericValue Long longField;
+    @Inject @NumericValue long primitiveLongField;
+    @Inject @BooleanValue Boolean booleanField;
+    @Inject @BooleanValue boolean primitiveBooleanField;
+    @Inject @NumericValue Byte byteField;
+    @Inject @NumericValue byte primitiveByteField;
+    @Inject @NumericValue Short shortField;
+    @Inject @NumericValue short primitiveShortField;
+    @Inject @NumericValue Float floatField;
+    @Inject @NumericValue float primitiveFloatField;
+    @Inject @NumericValue Double doubleField;
+    @Inject @NumericValue short primitiveDoubleField;
+    @Inject @EnumValue Bar enumField;
+    @Inject @ClassName Class<?> classField;
   }
 
   public enum Bar {
     TEE, BAZ, BOB;
   }
 
-  @Named("foo")
-  public void testNamed() throws NoSuchMethodException {
-    Named named = getClass().getMethod("testNamed").getAnnotation(Named.class);
-    assertEquals(named, new NamedImpl("foo"));
-    assertEquals(new NamedImpl("foo"), named);
-
-    assertEquals(Key.get(String.class, new NamedImpl("foo")),
-        Key.get(String.class, named));
-  }
-
   public void testOneConstantInjection() throws ContainerCreationException {
     ContainerBuilder builder = new ContainerBuilder();
-    builder.bind("#").to("5");
+    builder.bindConstant(NumericValue.class).to("5");
     builder.bind(Simple.class);
     Container container = builder.create(false);
     Simple simple = container.getFactory(Simple.class).get();
@@ -69,19 +77,15 @@
   }
 
   static class Simple {
-    @Inject @Named("#") int i;
+    @Inject @NumericValue int i;
   }
 
   public void testConstantInjection() throws ContainerCreationException {
-    Map<String, String> properties = new HashMap<String, String>() {{
-      put("#", "5");
-      put("boolean", "true");
-      put("enum", "TEE");
-      put("class", Foo.class.getName());
-    }};
-
     ContainerBuilder b = new ContainerBuilder();
-    b.bindProperties(properties);
+    b.bindConstant(NumericValue.class).to("5");
+    b.bindConstant(BooleanValue.class).to("true");
+    b.bindConstant(EnumValue.class).to("TEE");
+    b.bindConstant(ClassName.class).to(Foo.class.getName());
     Container c = b.create(false);
     Foo foo = c.getFactory(Foo.class).get();
 
@@ -112,7 +116,7 @@
 
   public void testInvalidInteger() throws ContainerCreationException {
     ContainerBuilder b = new ContainerBuilder();
-    b.bind("#").to("invalid");
+    b.bindConstant(NumericValue.class).to("invalid");
     Container c = b.create(false);
     try {
       c.getFactory(InvalidInteger.class).get();
@@ -121,12 +125,12 @@
   }
 
   public static class InvalidInteger {
-    @Inject @Named("#") Integer integerField;
+    @Inject @NumericValue Integer integerField;
   }
 
   public void testInvalidCharacter() throws ContainerCreationException {
     ContainerBuilder b = new ContainerBuilder();
-    b.bind("foo").to("invalid");
+    b.bindConstant(NumericValue.class).to("invalid");
     Container c = b.create(false);
     try {
       c.getFactory(InvalidCharacter.class).get();
@@ -135,12 +139,12 @@
   }
 
   public static class InvalidCharacter {
-    @Inject @Named("foo") char foo;
+    @Inject @NumericValue char foo;
   }
 
   public void testInvalidEnum() throws ContainerCreationException {
     ContainerBuilder b = new ContainerBuilder();
-    b.bind("foo").to("invalid");
+    b.bindConstant(NumericValue.class).to("invalid");
     Container c = b.create(false);
     try {
       c.getFactory(InvalidEnum.class).get();
@@ -149,6 +153,6 @@
   }
 
   public static class InvalidEnum {
-    @Inject @Named("foo") Bar foo;
+    @Inject @NumericValue Bar foo;
   }
 }
diff --git a/test/com/google/inject/ContainerTest.java b/test/com/google/inject/ContainerTest.java
index 7fce43d..3457998 100644
--- a/test/com/google/inject/ContainerTest.java
+++ b/test/com/google/inject/ContainerTest.java
@@ -29,6 +29,14 @@
   @ForBinding
   @interface Other {}
 
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface S {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface I {}
+
   public void testFactoryMethods() throws ContainerCreationException {
     Singleton singleton = new Singleton();
     Singleton other = new Singleton();
@@ -84,8 +92,8 @@
       protected void configure() {
         bind(Bar.class).to(BarImpl.class);
         bind(Tee.class).to(TeeImpl.class);
-        bind("s").to("test");
-        bind("i").to(5);
+        bindConstant(S.class).to("test");
+        bindConstant(I.class).to(5);
       }
     });
 
@@ -103,14 +111,14 @@
   public void testIntAndIntegerAreInterchangeable()
       throws ContainerCreationException {
     ContainerBuilder builder = new ContainerBuilder();
-    builder.bind("i").to(5);
+    builder.bindConstant(I.class).to(5);
     Container container = builder.create(false);
     IntegerWrapper iw = container.getFactory(IntegerWrapper.class).get();
     assertEquals(5, (int) iw.i);
   }
 
   static class IntegerWrapper {
-    @Inject @Named("i") Integer i;
+    @Inject @I Integer i;
   }
 
   static class Foo {
@@ -118,12 +126,12 @@
     @Inject Bar bar;
     @Inject Bar copy;
 
-    @Inject @Named("s") String s;
+    @Inject @S String s;
 
     int i;
 
     @Inject
-    void setI(@Named("i") int i) {
+    void setI(@I int i) {
       this.i = i;
     }
   }
@@ -137,7 +145,7 @@
   @ContainerScoped
   static class BarImpl implements Bar {
 
-    @Inject @Named("i") int i;
+    @Inject @I int i;
 
     Tee tee;
 
@@ -167,7 +175,7 @@
     @Inject Bar bar;
 
     @Inject
-    TeeImpl(@Named("s") String s) {
+    TeeImpl(@S String s) {
       this.s = s;
     }
 
@@ -222,8 +230,8 @@
 
   public void testInjectStatics() throws ContainerCreationException {
     ContainerBuilder builder = new ContainerBuilder();
-    builder.bind("s").to("test");
-    builder.bind("i").to(5);
+    builder.bindConstant(S.class).to("test");
+    builder.bindConstant(I.class).to(5);
     builder.requestStaticInjection(Static.class);
     builder.create(false);
 
@@ -233,11 +241,11 @@
 
   static class Static {
 
-    @Inject @Named("i") static int i;
+    @Inject @I static int i;
 
     static String s;
 
-    @Inject static void setS(@Named("s") String s) {
+    @Inject static void setS(@S String s) {
       Static.s = s;
     }
   }
diff --git a/test/com/google/inject/ErrorHandlingTest.java b/test/com/google/inject/ErrorHandlingTest.java
index 9dedd75..b5c4d23 100644
--- a/test/com/google/inject/ErrorHandlingTest.java
+++ b/test/com/google/inject/ErrorHandlingTest.java
@@ -17,6 +17,8 @@
 package com.google.inject;
 
 import java.util.List;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
 
 /**
  * @author crazybob@google.com (Bob Lee)
@@ -67,7 +69,7 @@
       bind(Bar.class);
       bind(Tee.class);
       bind(new TypeLiteral<List<String>>() {});
-      bind(String.class).annotatedWith(new NamedImpl("foo")).in("foo");
+      bind(String.class).annotatedWith(Names.annotationFor("foo")).in("foo");
       link(Key.get(Runnable.class)).to(Key.get(Runnable.class));
       requestStaticInjection(ErrorHandlingTest.class);
     }
diff --git a/test/com/google/inject/FactoryTest.java b/test/com/google/inject/FactoryTest.java
index 2306f15..97cffb3 100644
--- a/test/com/google/inject/FactoryTest.java
+++ b/test/com/google/inject/FactoryTest.java
@@ -20,6 +20,9 @@
 
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Annotation;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * @author crazybob@google.com (Bob Lee)
@@ -76,40 +79,64 @@
   static class One {}
   static class NegativeOne {}
 
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface FooAnnotation {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface BarAnnotation {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface TeeAnnotation1 {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface TeeAnnotation2 {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface BobAnnotation1 {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface BobAnnotation2 {}
+
   public void testInjection() throws Exception {
     ContainerBuilder cb = new ContainerBuilder();
 
     // Called from getInstance().
     cb.bind(Foo.class)
-        .named("foo")
-        .to(createFactory(Foo.class, "foo", null));
+        .annotatedWith(FooAnnotation.class)
+        .to(createFactory(Foo.class, FooAnnotation.class, null));
 
     // Called during preloading.
     cb.bind(Bar.class)
-        .named("fooBar")
-        .to(createFactory(Bar.class, "fooBar", null))
+        .annotatedWith(BarAnnotation.class)
+        .to(createFactory(Bar.class, BarAnnotation.class, null))
         .in(Scopes.CONTAINER);
 
     cb.bind(Tee.class)
-        .named("tee1")
-        .to(createFactory(Tee.class, "tee1",
+        .annotatedWith(TeeAnnotation1.class)
+        .to(createFactory(Tee.class, TeeAnnotation1.class,
             Bar.class.getDeclaredConstructor(Tee.class)));
 
     cb.bind(Tee.class)
-        .named("tee2")
-        .to(createFactory(Tee.class, "tee2",
+        .annotatedWith(TeeAnnotation2.class)
+        .to(createFactory(Tee.class, TeeAnnotation2.class,
             Bar.class.getDeclaredField("tee2")));
 
     final Method execute = Tee.class.getDeclaredMethod(
         "execute", Bob.class, Bob.class);
-    cb.bind(Bob.class).named("bob1").to(
-        createFactory(Bob.class, "bob1", execute));
-    cb.bind(Bob.class).named("bob2").to(
-        createFactory(Bob.class, "bob2", execute));
+    cb.bind(Bob.class).annotatedWith(BobAnnotation1.class).to(
+        createFactory(Bob.class, BobAnnotation1.class, execute));
+    cb.bind(Bob.class).annotatedWith(BobAnnotation2.class).to(
+        createFactory(Bob.class, BobAnnotation2.class, execute));
 
     Container c = cb.create(true);
 
-    Foo foo = c.getFactory(Key.get(Foo.class, "foo")).get();
+    Foo foo = c.getFactory(Key.get(Foo.class, FooAnnotation.class)).get();
 
     assertNotNull(foo.bar);
     assertNotNull(foo.bar.tee1);
@@ -121,11 +148,11 @@
   }
 
   <T> ContextualFactory<T> createFactory(
-      final Class<T> type, final String name, final Member expectedMember) {
+      final Class<T> type, final Class<? extends Annotation> annotationType,
+      final Member expectedMember) {
     return new ContextualFactory<T>() {
       public T get(Context context) {
         assertEquals(expectedMember, context.getMember());
-        //assertEquals(name, context.getKey().getName());
         assertEquals(type, context.getKey().getType().getType());
         return context.getContainer().getFactory(type).get();
       }
@@ -134,15 +161,15 @@
 
   static class Foo {
     final Bar bar;
-    @Inject Foo(@Named("fooBar") Bar bar) {
+    @Inject Foo(@BarAnnotation Bar bar) {
       this.bar = bar;
     }
   }
 
   static class Bar {
-    @Inject @Named("tee2") Tee tee2;
+    @Inject @TeeAnnotation2 Tee tee2;
     final Tee tee1;
-    @Inject Bar(@Named("tee1") Tee tee1) {
+    @Inject Bar(@TeeAnnotation1 Tee tee1) {
       this.tee1 = tee1;
     }
   }
@@ -150,8 +177,8 @@
   static class Tee {
     Bob bob1, bob2;
     @Inject void execute(
-        @Named("bob1") Bob bob1,
-        @Named("bob2") Bob bob2) {
+        @BobAnnotation1 Bob bob1,
+        @BobAnnotation2 Bob bob2) {
       this.bob1 = bob1;
       this.bob2 = bob2;
     }
diff --git a/test/com/google/inject/KeyTest.java b/test/com/google/inject/KeyTest.java
index 1c4b490..a4778c1 100644
--- a/test/com/google/inject/KeyTest.java
+++ b/test/com/google/inject/KeyTest.java
@@ -44,8 +44,8 @@
 
   public void testEquality() {
     assertEquals(
-      new Key<List<String>>("foo") {},
-      Key.get(new TypeLiteral<List<String>>() {}, "foo")
+      new Key<List<String>>(Foo.class) {},
+      Key.get(new TypeLiteral<List<String>>() {}, Foo.class)
     );
   }
 
diff --git a/test/com/google/inject/PerformanceComparison.java b/test/com/google/inject/PerformanceComparison.java
index e5f7a77..8827c3a 100644
--- a/test/com/google/inject/PerformanceComparison.java
+++ b/test/com/google/inject/PerformanceComparison.java
@@ -27,6 +27,8 @@
 
 import java.text.DecimalFormat;
 import java.util.concurrent.Callable;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * A semi-useless microbenchmark. Spring and Guice constuct the same object
@@ -101,8 +103,8 @@
           bind(Tee.class).to(TeeImpl.class);
           bind(Bar.class).to(BarImpl.class);
           bind(Foo.class);
-          bind("i").to(5);
-          bind("s").to("test");
+          bindConstant(I.class).to(5);
+          bindConstant(S.class).to("test");
         }
       });
 
@@ -162,7 +164,7 @@
     int i;
 
     @Inject
-    public void setI(@Named("i") int i) {
+    public void setI(@I int i) {
       this.i = i;
     }
 
@@ -177,7 +179,7 @@
     }
 
     @Inject
-    public void setS(@Named("s") String s) {
+    public void setS(@S String s) {
       this.s = s;
     }
   }
@@ -194,7 +196,7 @@
     final Tee tee;
 
     @Inject
-    public BarImpl(Tee tee, @Named("i") int i) {
+    public BarImpl(Tee tee, @I int i) {
       this.tee = tee;
       this.i = i;
     }
@@ -219,7 +221,7 @@
     final String s;
 
     @Inject
-    public TeeImpl(@Named("s") String s) {
+    public TeeImpl(@S String s) {
       this.s = s;
     }
 
@@ -227,4 +229,12 @@
       return s;
     }
   }
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface I {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface S {}
 }
diff --git a/test/com/google/inject/ReflectionTest.java b/test/com/google/inject/ReflectionTest.java
index 1815411..3fc62d5 100644
--- a/test/com/google/inject/ReflectionTest.java
+++ b/test/com/google/inject/ReflectionTest.java
@@ -17,12 +17,18 @@
 package com.google.inject;
 
 import junit.framework.TestCase;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * @author crazybob@google.com (Bob Lee)
  */
 public class ReflectionTest extends TestCase {
 
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface I {}
+
   public void testNormalBinding() throws ContainerCreationException {
     ContainerBuilder builder = new ContainerBuilder();
     Foo foo = new Foo();
@@ -37,12 +43,12 @@
 
   public void testConstantBinding() throws ContainerCreationException {
     ContainerBuilder builder = new ContainerBuilder();
-    builder.bind("i").to(5);
+    builder.bindConstant(I.class).to(5);
     Container container = builder.create(false);
-    Binding<?> i = container.getBinding(Key.get(int.class, "i"));
+    Binding<?> i = container.getBinding(Key.get(int.class, I.class));
     assertEquals(5, i.getFactory().get());
     assertNotNull(i.getSource());
-    assertEquals(Key.get(int.class, "i"), i.getKey());
+    assertEquals(Key.get(int.class, I.class), i.getKey());
     assertTrue(i.isConstant());
   }
 
diff --git a/test/com/google/inject/StaticInjectionTest.java b/test/com/google/inject/StaticInjectionTest.java
index 5dcd169..c29d564 100644
--- a/test/com/google/inject/StaticInjectionTest.java
+++ b/test/com/google/inject/StaticInjectionTest.java
@@ -17,16 +17,26 @@
 package com.google.inject;
 
 import junit.framework.TestCase;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * @author crazybob@google.com (Bob Lee)
  */
 public class StaticInjectionTest extends TestCase {
 
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface I {}
+
+  @Retention(RUNTIME)
+  @ForBinding
+  @interface S {}
+
   public void testInjectStatics() throws ContainerCreationException {
     ContainerBuilder builder = new ContainerBuilder();
-    builder.bind("s").to("test");
-    builder.bind("i").to(5);
+    builder.bindConstant(S.class).to("test");
+    builder.bindConstant(I.class).to(5);
     builder.requestStaticInjection(StaticInjectionTest.Static.class);
 
     Container c = builder.create(false);
@@ -37,11 +47,11 @@
 
   static class Static {
 
-    @Inject @Named("i") static int i;
+    @Inject @I static int i;
 
     static String s;
 
-    @Inject static void setS(@Named("s") String s) {
+    @Inject static void setS(@S String s) {
       StaticInjectionTest.Static.s = s;
     }
   }