Implemented ProxyFactory.

git-svn-id: https://google-guice.googlecode.com/svn/trunk@62 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/build.properties b/build.properties
index fa25685..d2d3374 100644
--- a/build.properties
+++ b/build.properties
@@ -3,4 +3,4 @@
 src.dir=src
 test.dir=test
 build.dir=build
-javadoc.packagenames=com.google.inject
+javadoc.packagenames=com.google.inject,com.google.inject.spi,com.google.inject.intercept
diff --git a/guice.iml b/guice.iml
index e507620..3064cae 100644
--- a/guice.iml
+++ b/guice.iml
@@ -49,6 +49,15 @@
       </library>
     </orderEntry>
     <orderEntry type="library" name="cglib-nodep-2.1_3" level="project" />
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MODULE_DIR$/lib/aopalliance.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
     <orderEntryProperties />
   </component>
 </module>
diff --git a/guice.iws b/guice.iws
index 706aabd..4730906 100644
--- a/guice.iws
+++ b/guice.iws
@@ -18,21 +18,14 @@
   </component>
   <component name="ChangeListManager">
     <list default="true" name="Default" comment="">
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/ContextualCallable.java" afterPath="$PROJECT_DIR$/src/com/google/inject/ContextualCallable.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java" afterPath="$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java" afterPath="$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java" afterPath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java" afterPath="$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/ConstructorInjector.java" afterPath="$PROJECT_DIR$/src/com/google/inject/ConstructorInjector.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/lib/aopalliance.jar" />
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/guice.iml" afterPath="$PROJECT_DIR$/guice.iml" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/guice.iws" afterPath="$PROJECT_DIR$/guice.iws" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java" afterPath="$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java" afterPath="$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java" afterPath="$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/Query.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/Query.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/test/com/google/inject/intercept/ProxyFactoryTest.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/MethodAspect.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/InterceptorStackCallback.java" />
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" afterPath="$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java" />
     </list>
   </component>
   <component name="ChangeListSynchronizer" />
@@ -202,183 +195,10 @@
   </component>
   <component name="FileEditorManager">
     <leaf>
-      <file leaf-file-name="ConstructionProxy.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java">
+      <file leaf-file-name="Message.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/Message.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ConstructionProxyFactory.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ContainerCreationException.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerCreationException.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="38" column="0" selection-start="1207" selection-end="1207" vertical-scroll-proportion="0.6612642">
-              <folding>
-                <element signature="imports" expanded="true" />
-              </folding>
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ErrorMessages.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ReflectionTest.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="AbstractQuery.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="TypeLiteral.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/TypeLiteral.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="32" column="8" selection-start="1141" selection-end="1141" vertical-scroll-proportion="0.027552674">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="Binding.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/Binding.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="0" column="0" selection-start="0" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ContainerBuilder.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerBuilder.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="334" column="31" selection-start="10275" selection-end="10275" vertical-scroll-proportion="0.3922204">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ConstantFactory.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ConstantFactory.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="38" column="14" selection-start="1098" selection-end="1098" vertical-scroll-proportion="0.6337115">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ContainerScope.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerScope.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="50" column="15" selection-start="1625" selection-end="1625" vertical-scroll-proportion="0.9918963">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="Queries.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="guice.iws" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/guice.iws">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="871" column="2" selection-start="44011" selection-end="44011" vertical-scroll-proportion="0.3936877">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="Query.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Query.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="QueryTest.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="package-info.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/package-info.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="18" column="3" selection-start="647" selection-end="647" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ContainerImpl.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContainerImpl.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="51" column="6" selection-start="1627" selection-end="1627" vertical-scroll-proportion="0.3306321">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ConstructorInjector.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ConstructorInjector.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="15" column="0" selection-start="596" selection-end="596" vertical-scroll-proportion="0.027552674">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ContextualCallable.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ContextualCallable.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="AllTests.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/test/com/google/inject/AllTests.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="49" column="19" selection-start="1724" selection-end="1724" vertical-scroll-proportion="0.7714749">
+            <state line="45" column="3" selection-start="1286" selection-end="1286" vertical-scroll-proportion="0.8541329">
               <folding />
             </state>
           </provider>
@@ -387,7 +207,92 @@
       <file leaf-file-name="ProxyFactory.java" pinned="false" current="false" current-in-tab="false">
         <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+            <state line="148" column="48" selection-start="5256" selection-end="5256" vertical-scroll-proportion="0.48460293">
+              <folding>
+                <element signature="imports" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="FastClass.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/reflect/FastClass.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="38" column="0" selection-start="1207" selection-end="1207" vertical-scroll-proportion="0.33225283">
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="ProxyFactoryTest.java" pinned="false" current="true" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/ProxyFactoryTest.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="23" column="7" selection-start="654" selection-end="654" vertical-scroll-proportion="0.6337115">
+              <folding>
+                <element signature="imports" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="MethodInterceptor.class" pinned="false" current="false" current-in-tab="false">
+        <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/MethodInterceptor.class">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="5" column="17" selection-start="167" selection-end="167" vertical-scroll-proportion="0.110210694">
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="InterceptorStackCallback.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/InterceptorStackCallback.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="23" column="9" selection-start="596" selection-end="596" vertical-scroll-proportion="0.016207455">
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="MethodProxy.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/MethodProxy.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="164" column="18" selection-start="6352" selection-end="6352" vertical-scroll-proportion="1.3111831">
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="Joinpoint.class" pinned="false" current="false" current-in-tab="false">
+        <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/Joinpoint.class">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="11" column="37" selection-start="313" selection-end="313" vertical-scroll-proportion="0.27552673">
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="Enhancer.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/Enhancer.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="589" column="23" selection-start="26039" selection-end="26039" vertical-scroll-proportion="0.33225283">
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="DuplicatesPredicate.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/DuplicatesPredicate.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="20" column="13" selection-start="712" selection-end="712" vertical-scroll-proportion="0.13776337">
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="ReflectUtils.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/ReflectUtils.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="344" column="23" selection-start="13257" selection-end="13257" vertical-scroll-proportion="0.5656402">
               <folding />
             </state>
           </provider>
@@ -396,61 +301,65 @@
       <file leaf-file-name="ProxyFactoryBuilder.java" pinned="false" current="false" current-in-tab="false">
         <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+            <state line="39" column="36" selection-start="1268" selection-end="1268" vertical-scroll-proportion="0.68881685">
+              <folding>
+                <element signature="imports" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="Query.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Query.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="23" column="17" selection-start="764" selection-end="764" vertical-scroll-proportion="0.24797407">
               <folding />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="InternalContext.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/InternalContext.java">
+      <file leaf-file-name="QueryTest.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="71" column="1" selection-start="2161" selection-end="2161" vertical-scroll-proportion="1.5429498">
+            <state line="34" column="13" selection-start="1234" selection-end="1234" vertical-scroll-proportion="0.24797407">
               <folding />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="PerformanceComparison.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/test/com/google/inject/PerformanceComparison.java">
+      <file leaf-file-name="MethodAspect.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/MethodAspect.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="149" column="37" selection-start="5048" selection-end="5048" vertical-scroll-proportion="2.4246354">
+            <state line="25" column="22" selection-start="735" selection-end="735" vertical-scroll-proportion="0.68881685">
+              <folding>
+                <element signature="imports" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="Queries.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="28" column="13" selection-start="889" selection-end="889" vertical-scroll-proportion="0.30307943">
               <folding />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="NumberFormat.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="jar:///usr/local/src.zip!/java/text/NumberFormat.java">
+      <file leaf-file-name="ConstructionProxy.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="509" column="9" selection-start="19846" selection-end="19846" vertical-scroll-proportion="0.28200972">
+            <state line="26" column="17" selection-start="837" selection-end="837" vertical-scroll-proportion="0.3306321">
               <folding />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="ConstructionContext.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/ConstructionContext.java">
+      <file leaf-file-name="ConstructionProxyFactory.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="30" column="6" selection-start="973" selection-end="973" vertical-scroll-proportion="-1.0858995">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ToStringCreator.class" pinned="false" current="false" current-in-tab="false">
-        <entry file="jar://$PROJECT_DIR$/lib/build/spring-core.jar!/org/springframework/core/style/ToStringCreator.class">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="5" column="13" selection-start="168" selection-end="168" vertical-scroll-proportion="0.110210694">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ToStringBuilder.java" pinned="false" current="true" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.38573745">
+            <state line="25" column="17" selection-start="785" selection-end="785" vertical-scroll-proportion="0.30307943">
               <folding />
             </state>
           </provider>
@@ -459,7 +368,7 @@
       <file leaf-file-name="DefaultConstructionProxyFactory.java" pinned="false" current="false" current-in-tab="false">
         <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+            <state line="46" column="0" selection-start="1116" selection-end="1602" vertical-scroll-proportion="0.88168555">
               <folding>
                 <element signature="imports" expanded="true" />
               </folding>
@@ -650,6 +559,32 @@
           <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
         </PATH_ELEMENT>
         <PATH_ELEMENT>
+          <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/src" />
+          <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+        </PATH_ELEMENT>
+        <PATH_ELEMENT>
+          <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/src/com/google/inject" />
+          <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+        </PATH_ELEMENT>
+        <PATH_ELEMENT>
+          <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/src/com/google/inject/intercept" />
+          <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+        </PATH_ELEMENT>
+      </PATH>
+      <PATH>
+        <PATH_ELEMENT>
+          <option name="myItemId" value="guice.ipr" />
+          <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+        </PATH_ELEMENT>
+        <PATH_ELEMENT>
+          <option name="myItemId" value="guice" />
+          <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+        </PATH_ELEMENT>
+        <PATH_ELEMENT>
+          <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+          <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+        </PATH_ELEMENT>
+        <PATH_ELEMENT>
           <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/lib" />
           <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
         </PATH_ELEMENT>
@@ -660,7 +595,7 @@
     <option name="STATE" value="0" />
   </component>
   <component name="ProjectView">
-    <navigator currentView="ProjectPane" proportions="0.16666667" version="1" splitterProportion="0.5">
+    <navigator currentView="PackagesPane" proportions="0.16666667" version="1" splitterProportion="0.5">
       <flattenPackages PackagesPane="true" />
       <showMembers />
       <showModules PackagesPane="false" />
@@ -725,16 +660,16 @@
     </key>
   </component>
   <component name="RestoreUpdateTree" />
-  <component name="RunManager" selected="JUnit.AllTests">
-    <tempConfiguration default="false" name="QueryTest" type="JUnit" factoryName="JUnit" enabled="false" merge="false">
-      <pattern value="com.google.inject.*" />
+  <component name="RunManager" selected="JUnit.ProxyFactoryTest.testSimpleCase">
+    <tempConfiguration default="false" name="ProxyFactoryTest.testSimpleCase" type="JUnit" factoryName="JUnit" enabled="false" merge="false">
+      <pattern value="com.google.inject.intercept.*" />
       <module name="guice" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" />
       <option name="PACKAGE_NAME" value="com.google.inject.intercept" />
-      <option name="MAIN_CLASS_NAME" value="com.google.inject.intercept.QueryTest" />
-      <option name="METHOD_NAME" />
-      <option name="TEST_OBJECT" value="class" />
+      <option name="MAIN_CLASS_NAME" value="com.google.inject.intercept.ProxyFactoryTest" />
+      <option name="METHOD_NAME" value="testSimpleCase" />
+      <option name="TEST_OBJECT" value="method" />
       <option name="VM_PARAMETERS" />
       <option name="PARAMETERS" />
       <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
@@ -742,13 +677,7 @@
       <option name="TEST_SEARCH_SCOPE">
         <value defaultName="wholeProject" />
       </option>
-      <RunnerSettings RunnerId="Debug">
-        <option name="DEBUG_PORT" value="41735" />
-        <option name="TRANSPORT" value="0" />
-        <option name="LOCAL" value="true" />
-      </RunnerSettings>
       <RunnerSettings RunnerId="Run" />
-      <ConfigurationWrapper RunnerId="Debug" />
       <ConfigurationWrapper RunnerId="Run" />
       <method>
         <option name="Make" value="true" />
@@ -942,7 +871,7 @@
   </component>
   <component name="ToolWindowManager">
     <frame x="4" y="44" width="1916" height="1156" extended-state="0" />
-    <editor active="false" />
+    <editor active="true" />
     <layout>
       <window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
       <window_info id="CVS" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
@@ -960,7 +889,7 @@
       <window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
       <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.14623655" order="1" />
       <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3282876" order="8" />
-      <window_info id="Run" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.40018922" order="2" />
+      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.40018922" order="2" />
       <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="2" />
       <window_info id="File View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="6" />
       <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39978448" order="0" />
@@ -1059,113 +988,121 @@
     <option name="myLastEditedConfigurable" value="Default" />
   </component>
   <component name="editorHistoryManager">
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/ErrorMessages.java">
+    <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/ReflectUtils.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+        <state line="344" column="23" selection-start="13257" selection-end="13257" vertical-scroll-proportion="0.5656402">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/test/com/google/inject/ReflectionTest.java">
+    <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/core/DuplicatesPredicate.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+        <state line="20" column="13" selection-start="712" selection-end="712" vertical-scroll-proportion="0.13776337">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/AbstractQuery.java">
+    <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/Message.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+        <state line="45" column="3" selection-start="1286" selection-end="1286" vertical-scroll-proportion="0.8541329">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java">
+    <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/Joinpoint.class">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+        <state line="11" column="37" selection-start="313" selection-end="313" vertical-scroll-proportion="0.27552673">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java">
+    <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/MethodProxy.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Queries.java">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/Query.java">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/guice.iws">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="871" column="2" selection-start="44011" selection-end="44011" vertical-scroll-proportion="0.3936877">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/QueryTest.java">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+        <state line="164" column="18" selection-start="6352" selection-end="6352" vertical-scroll-proportion="1.3111831">
           <folding />
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxy.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/ConstructionProxyFactory.java">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+        <state line="26" column="17" selection-start="837" selection-end="837" vertical-scroll-proportion="0.3306321">
           <folding />
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/google/inject/spi/DefaultConstructionProxyFactory.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0">
+        <state line="46" column="0" selection-start="1116" selection-end="1602" vertical-scroll-proportion="0.88168555">
           <folding>
             <element signature="imports" expanded="true" />
           </folding>
         </state>
       </provider>
     </entry>
-    <entry file="jar://$PROJECT_DIR$/lib/build/spring-core.jar!/org/springframework/core/style/ToStringCreator.class">
+    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/InterceptorStackCallback.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="5" column="13" selection-start="168" selection-end="168" vertical-scroll-proportion="0.110210694">
+        <state line="23" column="9" selection-start="596" selection-end="596" vertical-scroll-proportion="0.016207455">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/COPYING">
+    <entry file="jar://$PROJECT_DIR$/lib/aopalliance.jar!/org/aopalliance/intercept/MethodInterceptor.class">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="-3.857143">
+        <state line="5" column="17" selection-start="167" selection-end="167" vertical-scroll-proportion="0.110210694">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/google/inject/util/ToStringBuilder.java">
+    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/MethodAspect.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="3" selection-start="595" selection-end="595" vertical-scroll-proportion="0.38573745">
+        <state line="25" column="22" selection-start="735" selection-end="735" vertical-scroll-proportion="0.68881685">
+          <folding>
+            <element signature="imports" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactoryBuilder.java">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="39" column="36" selection-start="1268" selection-end="1268" vertical-scroll-proportion="0.68881685">
+          <folding>
+            <element signature="imports" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/proxy/Enhancer.java">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="589" column="23" selection-start="26039" selection-end="26039" vertical-scroll-proportion="0.33225283">
           <folding />
         </state>
       </provider>
     </entry>
+    <entry file="jar://$PROJECT_DIR$/lib/build/cglib-src-2.1_3.jar!/net/sf/cglib/reflect/FastClass.java">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="38" column="0" selection-start="1207" selection-end="1207" vertical-scroll-proportion="0.33225283">
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/src/com/google/inject/intercept/ProxyFactory.java">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="148" column="48" selection-start="5256" selection-end="5256" vertical-scroll-proportion="0.48460293">
+          <folding>
+            <element signature="imports" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/test/com/google/inject/intercept/ProxyFactoryTest.java">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="23" column="7" selection-start="654" selection-end="654" vertical-scroll-proportion="0.6337115">
+          <folding>
+            <element signature="imports" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
   </component>
 </project>
 
diff --git a/lib/aopalliance.jar b/lib/aopalliance.jar
new file mode 100644
index 0000000..578b1a0
--- /dev/null
+++ b/lib/aopalliance.jar
Binary files differ
diff --git a/src/com/google/inject/intercept/InterceptorStackCallback.java b/src/com/google/inject/intercept/InterceptorStackCallback.java
new file mode 100644
index 0000000..703c4a8
--- /dev/null
+++ b/src/com/google/inject/intercept/InterceptorStackCallback.java
@@ -0,0 +1,78 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+package com.google.inject.intercept;
+
+import net.sf.cglib.proxy.MethodProxy;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.AccessibleObject;
+import java.util.List;
+
+/**
+ * Intercepts a method with a stack of interceptors.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+class InterceptorStackCallback implements net.sf.cglib.proxy.MethodInterceptor {
+
+  final MethodInterceptor[] interceptors;
+  final Method method;
+
+  public InterceptorStackCallback(Method method,
+      List<MethodInterceptor> interceptors) {
+    this.method = method;
+    this.interceptors = interceptors.toArray(
+        new MethodInterceptor[interceptors.size()]);
+  }
+
+  public Object intercept(Object proxy, Method method, Object[] arguments,
+      MethodProxy methodProxy) throws Throwable {
+    return new InterceptedMethodInvocation(
+        proxy, methodProxy, arguments).proceed();
+  }
+
+  class InterceptedMethodInvocation implements MethodInvocation {
+
+    final Object proxy;
+    final Object[] arguments;
+    final MethodProxy methodProxy;
+    int index = -1;
+
+    public InterceptedMethodInvocation(Object proxy, MethodProxy methodProxy,
+        Object[] arguments) {
+      this.proxy = proxy;
+      this.methodProxy = methodProxy;
+      this.arguments = arguments;
+    }
+
+    public Object proceed() throws Throwable {
+      try {
+        index++;
+        return index == interceptors.length
+          ? methodProxy.invokeSuper(proxy, arguments)
+          : interceptors[index].invoke(this);
+      } finally {
+        index--;
+      }
+    }
+
+    public Method getMethod() {
+      return method;
+    }
+
+    public Object[] getArguments() {
+      return arguments;
+    }
+
+    public Object getThis() {
+      return proxy;
+    }
+
+    public AccessibleObject getStaticPart() {
+      return getMethod();
+    }
+  }
+}
diff --git a/src/com/google/inject/intercept/MethodAspect.java b/src/com/google/inject/intercept/MethodAspect.java
new file mode 100644
index 0000000..ff5765d
--- /dev/null
+++ b/src/com/google/inject/intercept/MethodAspect.java
@@ -0,0 +1,40 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+package com.google.inject.intercept;
+
+import com.google.inject.util.Objects;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.lang.reflect.Method;
+
+/**
+ * Ties a query to a method interceptor.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ */
+class MethodAspect {
+
+  final Query<? super Class> classQuery;
+  final Query<? super Method> methodQuery;
+  final MethodInterceptor interceptor;
+
+  MethodAspect(Query<? super Class> classQuery, Query<? super Method> methodQuery,
+      MethodInterceptor interceptor) {
+    this.classQuery = Objects.nonNull(classQuery, "class query");
+    this.methodQuery = Objects.nonNull(methodQuery, "method query");
+    this.interceptor = Objects.nonNull(interceptor, "interceptor");
+  }
+
+  boolean matches(Class<?> clazz) {
+    return classQuery.matches(clazz);
+  }
+
+  boolean matches(Method method) {
+    return methodQuery.matches(method);
+  }
+
+  MethodInterceptor interceptor() {
+    return interceptor;
+  }
+}
diff --git a/src/com/google/inject/intercept/ProxyFactory.java b/src/com/google/inject/intercept/ProxyFactory.java
index 039844c..719acba 100644
--- a/src/com/google/inject/intercept/ProxyFactory.java
+++ b/src/com/google/inject/intercept/ProxyFactory.java
@@ -16,9 +16,171 @@
 
 package com.google.inject.intercept;
 
+import com.google.inject.spi.ConstructionProxyFactory;
+import com.google.inject.spi.ConstructionProxy;
+import com.google.inject.spi.DefaultConstructionProxyFactory;
+import com.google.inject.util.ReferenceCache;
+
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.NoOp;
+import net.sf.cglib.proxy.CallbackFilter;
+import net.sf.cglib.reflect.FastClass;
+import net.sf.cglib.reflect.FastConstructor;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
 /**
+ * Proxies classes applying interceptors to methods as specified in
+ * {@link ProxyFactoryBuilder}.
+ *
  * @author crazybob@google.com (Bob Lee)
  */
-public interface ProxyFactory {
+public class ProxyFactory implements ConstructionProxyFactory {
 
+  final List<MethodAspect> methodAspects;
+  final ConstructionProxyFactory defaultFactory =
+      new DefaultConstructionProxyFactory();
+
+  ProxyFactory(List<MethodAspect> methodAspects) {
+    this.methodAspects = methodAspects;
+  }
+
+  Map<Constructor<?>, ConstructionProxy<?>> constructionProxies =
+      new ReferenceCache<Constructor<?>, ConstructionProxy<?>>() {
+    protected ConstructionProxy<?> create(Constructor<?> constructor) {
+      return createConstructionProxy(constructor);
+    }
+  };
+
+  <T> ConstructionProxy<T> createConstructionProxy(Constructor<T> constructor) {
+    Class<T> declaringClass = constructor.getDeclaringClass();
+
+    // Find applicable aspects. Bow out if none are applicable to this class.
+    List<MethodAspect> applicableAspects = new ArrayList<MethodAspect>();
+    for (MethodAspect methodAspect : methodAspects) {
+      if (methodAspect.matches(declaringClass)) {
+        applicableAspects.add(methodAspect);
+      }
+    }
+    if (applicableAspects.isEmpty()) {
+      return defaultFactory.get(constructor);
+    }
+
+    // Get list of methods from cglib.
+    List<Method> methods = new ArrayList<Method>();
+    Enhancer.getMethods(declaringClass, null, methods);
+    final Map<Method, Integer> indices = new HashMap<Method, Integer>();
+
+    // Create method/interceptor holders and record indices.
+    List<MethodInterceptorsPair> methodInterceptorsPairs =
+        new ArrayList<MethodInterceptorsPair>();
+    for (int i = 0; i < methods.size(); i++) {
+      Method method = methods.get(i);
+      methodInterceptorsPairs.add(new MethodInterceptorsPair(method));
+      indices.put(method, i);
+    }
+
+    // Iterate over aspects and add interceptors for the methods they apply
+    // to.
+    boolean anyMatched = false;
+    for (MethodAspect methodAspect : applicableAspects) {
+      for (MethodInterceptorsPair methodInterceptorsPair
+          : methodInterceptorsPairs) {
+        if (methodAspect.matches(methodInterceptorsPair.method)) {
+          methodInterceptorsPair.add(methodAspect.interceptor());
+          anyMatched = true;
+        }
+      }
+    }
+    if (!anyMatched) {
+      return defaultFactory.get(constructor);
+    }
+
+    // Create callbacks.
+    Callback[] callbacks = new Callback[methods.size()];
+    Class<? extends Callback>[] callbackTypes = new Class[methods.size()];
+    for (int i = 0; i < methods.size(); i++) {
+      MethodInterceptorsPair methodInterceptorsPair =
+          methodInterceptorsPairs.get(i);
+      if (!methodInterceptorsPair.hasInterceptors()) {
+        callbacks[i] = NoOp.INSTANCE;
+        callbackTypes[i] = NoOp.class;
+      } else {
+        callbacks[i] = new InterceptorStackCallback(
+            methodInterceptorsPair.method, methodInterceptorsPair.interceptors);
+        callbackTypes[i] = net.sf.cglib.proxy.MethodInterceptor.class;
+      }
+    }
+
+    // Create the proxied class.
+    Enhancer enhancer = new Enhancer();
+    enhancer.setSuperclass(declaringClass);
+    enhancer.setUseCache(false); // We do enough caching.
+    enhancer.setCallbackFilter(new CallbackFilter() {
+      public int accept(Method method) {
+        return indices.get(method);
+      }
+    });
+    enhancer.setCallbackTypes(callbackTypes);
+    enhancer.setUseFactory(false);
+
+    Class<?> proxied = enhancer.createClass();
+
+    // Store callbacks.
+    Enhancer.registerStaticCallbacks(proxied, callbacks);
+
+    return createConstructionProxy(proxied, constructor.getParameterTypes());
+  }
+
+  /**
+   * Creates a construction proxy given a class and parameter types.
+   */
+  <T> ConstructionProxy<T> createConstructionProxy(Class<?> clazz,
+      Class[] parameterTypes) {
+    FastClass fastClass = FastClass.create(clazz);
+    final FastConstructor fastConstructor =
+        fastClass.getConstructor(parameterTypes);
+    return new ConstructionProxy<T>() {
+      @SuppressWarnings({"unchecked"})
+      public T newInstance(Object... arguments)
+          throws InvocationTargetException {
+        return (T) fastConstructor.newInstance(arguments);
+      }
+    };
+  }
+
+  static class MethodInterceptorsPair {
+
+    final Method method;
+    List<MethodInterceptor> interceptors;
+
+    public MethodInterceptorsPair(Method method) {
+      this.method = method;
+    }
+
+    void add(MethodInterceptor interceptor) {
+      if (interceptors == null) {
+        interceptors = new ArrayList<MethodInterceptor>();
+      }
+      interceptors.add(interceptor);
+    }
+
+    boolean hasInterceptors() {
+      return interceptors != null;
+    }
+  }
+
+  @SuppressWarnings({"unchecked"})
+  public <T> ConstructionProxy<T> get(Constructor<T> constructor) {
+    return (ConstructionProxy<T>) constructionProxies.get(constructor);
+  }
 }
diff --git a/src/com/google/inject/intercept/ProxyFactoryBuilder.java b/src/com/google/inject/intercept/ProxyFactoryBuilder.java
index 4b00f4e..bedcfe6 100644
--- a/src/com/google/inject/intercept/ProxyFactoryBuilder.java
+++ b/src/com/google/inject/intercept/ProxyFactoryBuilder.java
@@ -16,9 +16,37 @@
 
 package com.google.inject.intercept;
 
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.reflect.Method;
+
 /**
+ * Creates a {@link ProxyFactory}.
+ *
  * @author crazybob@google.com (Bob Lee)
  */
 public class ProxyFactoryBuilder {
 
+  final List<MethodAspect> methodAspects = new ArrayList<MethodAspect>();
+
+  /**
+   * Applies the given method interceptor to the methods matched by the class
+   * and method queries.
+   */
+  public ProxyFactoryBuilder intercept(Query<? super Class> classQuery,
+      Query<? super Method> methodQuery, MethodInterceptor interceptor) {
+    methodAspects.add(new MethodAspect(classQuery, methodQuery, interceptor));
+    return this;
+  }
+
+  /**
+   * Creates a {@code ProxyFactory}.
+   */
+  public ProxyFactory create() {
+    List<MethodAspect> methodAspects = new ArrayList<MethodAspect>();
+    methodAspects.addAll(this.methodAspects);
+    return new ProxyFactory(methodAspects);
+  }
 }
diff --git a/test/com/google/inject/intercept/ProxyFactoryTest.java b/test/com/google/inject/intercept/ProxyFactoryTest.java
new file mode 100644
index 0000000..c042eb8
--- /dev/null
+++ b/test/com/google/inject/intercept/ProxyFactoryTest.java
@@ -0,0 +1,54 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+package com.google.inject.intercept;
+
+import com.google.inject.spi.ConstructionProxy;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class ProxyFactoryTest extends TestCase {
+
+  public void testSimpleCase()
+      throws NoSuchMethodException, InvocationTargetException {
+    SimpleInterceptor interceptor = new SimpleInterceptor();
+
+    ProxyFactoryBuilder builder = new ProxyFactoryBuilder();
+    builder.intercept(Queries.any(), Queries.any(), interceptor);
+    ProxyFactory factory = builder.create();
+
+    ConstructionProxy<Simple> constructor =
+        factory.get(Simple.class.getDeclaredConstructor());
+
+    Simple simple = constructor.newInstance();
+    simple.invoke();
+    assertTrue(simple.invoked);
+    assertTrue(interceptor.invoked);
+  }
+
+  static class Simple {
+    boolean invoked = false;
+    public void invoke() {
+      invoked = true;
+    }
+  }
+
+  static class SimpleInterceptor implements MethodInterceptor {
+
+    boolean invoked = false;
+
+    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+      invoked = true;
+      return methodInvocation.proceed();
+    }
+  }
+
+
+}