Created
July 7, 2014 17:58
-
-
Save gissuebot/5e89c8647637450144e6 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 94, comment 27
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: test/com/google/inject/ProxyFactoryTest.java | |
=================================================================== | |
--- test/com/google/inject/ProxyFactoryTest.java (revision 345) | |
+++ test/com/google/inject/ProxyFactoryTest.java (working copy) | |
@@ -20,6 +20,7 @@ | |
import static com.google.inject.matcher.Matchers.any; | |
import static com.google.inject.matcher.Matchers.not; | |
import static com.google.inject.matcher.Matchers.only; | |
+import com.google.inject.internal.GuiceCodeGen; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.lang.reflect.InvocationTargetException; | |
@@ -34,11 +35,12 @@ | |
public void testSimpleCase() | |
throws NoSuchMethodException, InvocationTargetException { | |
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook()); | |
SimpleInterceptor interceptor = new SimpleInterceptor(); | |
ProxyFactoryBuilder builder = new ProxyFactoryBuilder(); | |
builder.intercept(any(), any(), interceptor); | |
- ProxyFactory factory = builder.create(); | |
+ ProxyFactory factory = builder.create(defaultCodeGen); | |
Provider<Simple> creator = factory.getFactory(Simple.class); | |
@@ -67,13 +69,14 @@ | |
public void testInterceptOneMethod() | |
throws NoSuchMethodException, InvocationTargetException { | |
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook()); | |
SimpleInterceptor interceptor = new SimpleInterceptor(); | |
ProxyFactoryBuilder builder = new ProxyFactoryBuilder(); | |
builder.intercept( | |
only(Bar.class), annotatedWith(Intercept.class), interceptor); | |
- ProxyFactory factory = builder.create(); | |
+ ProxyFactory factory = builder.create(defaultCodeGen); | |
ConstructionProxy<Foo> fooFactory = | |
factory.get(Foo.class.getDeclaredConstructor()); | |
@@ -124,11 +127,12 @@ | |
public void testWithConstructorArguments() | |
throws InvocationTargetException, NoSuchMethodException { | |
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook()); | |
SimpleInterceptor interceptor = new SimpleInterceptor(); | |
ProxyFactoryBuilder builder = new ProxyFactoryBuilder(); | |
builder.intercept(any(), any(), interceptor); | |
- ProxyFactory factory = builder.create(); | |
+ ProxyFactory factory = builder.create(defaultCodeGen); | |
ConstructionProxy<A> constructor = | |
factory.get(A.class.getDeclaredConstructor(int.class)); | |
@@ -140,11 +144,12 @@ | |
public void testNotProxied() | |
throws NoSuchMethodException, InvocationTargetException { | |
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook()); | |
SimpleInterceptor interceptor = new SimpleInterceptor(); | |
ProxyFactoryBuilder builder = new ProxyFactoryBuilder(); | |
builder.intercept(not(any()), not(any()), interceptor); | |
- ProxyFactory factory = builder.create(); | |
+ ProxyFactory factory = builder.create(defaultCodeGen); | |
ConstructionProxy<A> constructor = | |
factory.get(A.class.getDeclaredConstructor(int.class)); | |
@@ -163,12 +168,13 @@ | |
public void testMultipleInterceptors() | |
throws NoSuchMethodException, InvocationTargetException { | |
+ GuiceCodeGen defaultCodeGen = new GuiceCodeGen(new DefaultClassLoaderHook()); | |
DoubleInterceptor doubleInterceptor = new DoubleInterceptor(); | |
CountingInterceptor countingInterceptor = new CountingInterceptor(); | |
ProxyFactoryBuilder builder = new ProxyFactoryBuilder(); | |
builder.intercept(any(), any(), doubleInterceptor, countingInterceptor); | |
- ProxyFactory factory = builder.create(); | |
+ ProxyFactory factory = builder.create(defaultCodeGen); | |
ConstructionProxy<Counter> constructor = | |
factory.get(Counter.class.getDeclaredConstructor()); | |
Index: src/com/google/inject/ConstructorInjector.java | |
=================================================================== | |
--- src/com/google/inject/ConstructorInjector.java (revision 345) | |
+++ src/com/google/inject/ConstructorInjector.java (working copy) | |
@@ -123,7 +123,7 @@ | |
if (constructionContext.isConstructing()) { | |
// TODO (crazybob): if we can't proxy this object, can we proxy the | |
// other object? | |
- return constructionContext.createProxy(expectedType); | |
+ return constructionContext.createProxy(context.injector.codeGen, expectedType); | |
} | |
// If we're re-entering this factory while injecting fields or methods, | |
Index: src/com/google/inject/DefaultConstructionProxyFactory.java | |
=================================================================== | |
--- src/com/google/inject/DefaultConstructionProxyFactory.java (revision 345) | |
+++ src/com/google/inject/DefaultConstructionProxyFactory.java (working copy) | |
@@ -16,7 +16,7 @@ | |
package com.google.inject; | |
-import com.google.inject.internal.GuiceFastClass; | |
+import com.google.inject.internal.GuiceCodeGen; | |
import com.google.inject.internal.Objects; | |
import java.lang.reflect.Constructor; | |
import java.lang.reflect.InvocationTargetException; | |
@@ -33,6 +33,12 @@ | |
*/ | |
class DefaultConstructionProxyFactory implements ConstructionProxyFactory { | |
+ final GuiceCodeGen codeGen; | |
+ | |
+ public DefaultConstructionProxyFactory(GuiceCodeGen codeGen) { | |
+ this.codeGen = codeGen; | |
+ } | |
+ | |
public <T> ConstructionProxy<T> get(final Constructor<T> constructor) { | |
// We can't use FastConstructor if the constructor is private or protected. | |
if (Modifier.isPrivate(constructor.getModifiers()) | |
@@ -56,7 +62,7 @@ | |
} | |
Class<T> classToConstruct = constructor.getDeclaringClass(); | |
- FastClass fastClass = GuiceFastClass.create(classToConstruct); | |
+ FastClass fastClass = codeGen.getFastClass(classToConstruct); | |
final FastConstructor fastConstructor | |
= fastClass.getConstructor(constructor); | |
return new ConstructionProxy<T>() { | |
Index: src/com/google/inject/internal/GuiceFastClass.java | |
=================================================================== | |
--- src/com/google/inject/internal/GuiceFastClass.java (revision 345) | |
+++ src/com/google/inject/internal/GuiceFastClass.java (working copy) | |
@@ -1,39 +0,0 @@ | |
-/** | |
- * 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.internal; | |
- | |
-import net.sf.cglib.reflect.FastClass; | |
- | |
-/** | |
- * Gives Guice classes custom names. | |
- * | |
- * @author crazybob@google.com (Bob Lee) | |
- */ | |
-public class GuiceFastClass { | |
- | |
- public static FastClass create(Class type) { | |
- return create(type.getClassLoader(), type); | |
- } | |
- | |
- public static FastClass create(ClassLoader loader, Class type) { | |
- FastClass.Generator generator = new FastClass.Generator(); | |
- generator.setType(type); | |
- generator.setClassLoader(loader); | |
- generator.setNamingPolicy(new GuiceNamingPolicy()); | |
- return generator.create(); | |
- } | |
-} | |
Index: src/com/google/inject/internal/GuiceCodeGen.java | |
=================================================================== | |
--- src/com/google/inject/internal/GuiceCodeGen.java (revision 345) | |
+++ src/com/google/inject/internal/GuiceCodeGen.java (working copy) | |
@@ -16,6 +16,10 @@ | |
package com.google.inject.internal; | |
+import com.google.inject.ClassLoaderHook; | |
+import java.lang.reflect.InvocationHandler; | |
+import java.lang.reflect.Proxy; | |
+import net.sf.cglib.proxy.Enhancer; | |
import net.sf.cglib.reflect.FastClass; | |
/** | |
@@ -23,17 +27,42 @@ | |
* | |
* @author crazybob@google.com (Bob Lee) | |
*/ | |
-public class GuiceFastClass { | |
+public class GuiceCodeGen { | |
- public static FastClass create(Class type) { | |
- return create(type.getClassLoader(), type); | |
+ final ClassLoaderHook classLoaderHook; | |
+ | |
+ public GuiceCodeGen(ClassLoaderHook classLoaderHook) { | |
+ this.classLoaderHook = classLoaderHook; | |
} | |
- public static FastClass create(ClassLoader loader, Class type) { | |
+ public FastClass getFastClass(Class<?> type) { | |
+ ClassLoader loader = classLoaderHook.get(type.getClassLoader()); | |
FastClass.Generator generator = new FastClass.Generator(); | |
+ | |
generator.setType(type); | |
generator.setClassLoader(loader); | |
generator.setNamingPolicy(new GuiceNamingPolicy()); | |
+ | |
return generator.create(); | |
} | |
+ | |
+ public Enhancer getEnhancer(Class<?> type) { | |
+ Enhancer enhancer = new Enhancer() { | |
+ protected ClassLoader getDefaultClassLoader() { | |
+ return classLoaderHook.get(super.getDefaultClassLoader()); | |
+ } | |
+ }; | |
+ | |
+ enhancer.setSuperclass(type); | |
+ enhancer.setUseCache(false); // We do enough caching. | |
+ enhancer.setUseFactory(false); | |
+ enhancer.setNamingPolicy(new GuiceNamingPolicy()); | |
+ | |
+ return enhancer; | |
+ } | |
+ | |
+ public Object getProxy(Class<?> type, InvocationHandler handler) { | |
+ ClassLoader loader = classLoaderHook.get(type.getClassLoader()); | |
+ return Proxy.newProxyInstance(loader, new Class[] {type}, handler); | |
+ } | |
} | |
Index: src/com/google/inject/Guice.java | |
=================================================================== | |
--- src/com/google/inject/Guice.java (revision 345) | |
+++ src/com/google/inject/Guice.java (working copy) | |
@@ -88,10 +88,37 @@ | |
* construction | |
*/ | |
public static Injector createInjector(Stage stage, Iterable<Module> modules) { | |
+ return createInjector(new DefaultClassLoaderHook(), stage, modules); | |
+ } | |
+ | |
+ /** | |
+ * Creates an injector for the given set of modules, in a given development | |
+ * stage, with a given classloading hook. | |
+ * | |
+ * @throws CreationException if one or more errors occur during Injector | |
+ * construction | |
+ */ | |
+ public static Injector createInjector(ClassLoaderHook classLoaderHook, | |
+ Stage stage, Module... modules) { | |
+ | |
+ return createInjector(classLoaderHook, stage, Arrays.asList(modules)); | |
+ } | |
+ | |
+ /** | |
+ * Creates an injector for the given set of modules, in a given development | |
+ * stage, with a given classloading hook. | |
+ * | |
+ * @throws CreationException if one or more errors occur during Injector | |
+ * construction | |
+ */ | |
+ public static Injector createInjector(ClassLoaderHook classLoaderHook, | |
+ Stage stage, Iterable<Module> modules) { | |
+ | |
BinderImpl binder = new BinderImpl(stage); | |
for (Module module : modules) { | |
binder.install(module); | |
} | |
- return binder.createInjector(); | |
+ | |
+ return binder.createInjector(classLoaderHook); | |
} | |
} | |
Index: src/com/google/inject/InjectorImpl.java | |
=================================================================== | |
--- src/com/google/inject/InjectorImpl.java (revision 345) | |
+++ src/com/google/inject/InjectorImpl.java (working copy) | |
@@ -16,7 +16,7 @@ | |
package com.google.inject; | |
-import com.google.inject.internal.GuiceFastClass; | |
+import com.google.inject.internal.GuiceCodeGen; | |
import com.google.inject.internal.Objects; | |
import com.google.inject.internal.ReferenceCache; | |
import com.google.inject.internal.StackTraceElements; | |
@@ -83,6 +83,7 @@ | |
private static final Map<Class<?>, Converter<?>> PRIMITIVE_CONVERTERS | |
= new PrimitiveConverters(); | |
+ final GuiceCodeGen codeGen; | |
final ConstructionProxyFactory constructionProxyFactory; | |
final Map<Key<?>, BindingImpl<?>> bindings; | |
final BindingsMultimap bindingsMultimap = new BindingsMultimap(); | |
@@ -91,9 +92,11 @@ | |
ErrorHandler errorHandler = new InvalidErrorHandler(); | |
Object defaultSource = SourceProviders.UNKNOWN_SOURCE; | |
- InjectorImpl(ConstructionProxyFactory constructionProxyFactory, | |
+ InjectorImpl(GuiceCodeGen codeGen, | |
+ ConstructionProxyFactory constructionProxyFactory, | |
Map<Key<?>, BindingImpl<?>> bindings, | |
Map<Class<? extends Annotation>, Scope> scopes) { | |
+ this.codeGen = codeGen; | |
this.constructionProxyFactory = constructionProxyFactory; | |
this.bindings = bindings; | |
this.scopes = scopes; | |
@@ -549,7 +552,7 @@ | |
}; | |
} | |
else { | |
- FastClass fastClass = GuiceFastClass.create(method.getDeclaringClass()); | |
+ FastClass fastClass = injector.codeGen.getFastClass(method.getDeclaringClass()); | |
final FastMethod fastMethod = fastClass.getMethod(method); | |
this.methodInvoker = new MethodInvoker() { | |
Index: src/com/google/inject/ProxyFactory.java | |
=================================================================== | |
--- src/com/google/inject/ProxyFactory.java (revision 345) | |
+++ src/com/google/inject/ProxyFactory.java (working copy) | |
@@ -16,7 +16,7 @@ | |
package com.google.inject; | |
-import com.google.inject.internal.GuiceFastClass; | |
+import com.google.inject.internal.GuiceCodeGen; | |
import com.google.inject.internal.GuiceNamingPolicy; | |
import com.google.inject.internal.Objects; | |
import com.google.inject.internal.ReferenceCache; | |
@@ -43,12 +43,14 @@ | |
*/ | |
class ProxyFactory implements ConstructionProxyFactory { | |
+ final GuiceCodeGen codeGen; | |
final List<MethodAspect> methodAspects; | |
- final ConstructionProxyFactory defaultFactory | |
- = new DefaultConstructionProxyFactory(); | |
+ final ConstructionProxyFactory defaultFactory; | |
- ProxyFactory(List<MethodAspect> methodAspects) { | |
+ ProxyFactory(GuiceCodeGen codeGen, List<MethodAspect> methodAspects) { | |
+ this.codeGen = codeGen; | |
this.methodAspects = methodAspects; | |
+ this.defaultFactory = new DefaultConstructionProxyFactory(codeGen); | |
} | |
Map<Constructor<?>, ConstructionProxy<?>> constructionProxies | |
@@ -140,17 +142,13 @@ | |
} | |
// Create the proxied class. | |
- Enhancer enhancer = new Enhancer(); | |
- enhancer.setSuperclass(declaringClass); | |
- enhancer.setUseCache(false); // We do enough caching. | |
+ Enhancer enhancer = codeGen.getEnhancer(declaringClass); | |
enhancer.setCallbackFilter(new CallbackFilter() { | |
public int accept(Method method) { | |
return indices.get(method); | |
} | |
}); | |
enhancer.setCallbackTypes(callbackTypes); | |
- enhancer.setUseFactory(false); | |
- enhancer.setNamingPolicy(new GuiceNamingPolicy()); | |
Class<?> proxied = enhancer.createClass(); | |
@@ -165,7 +163,7 @@ | |
*/ | |
<T> ConstructionProxy<T> createConstructionProxy(Class<?> clazz, | |
Class[] parameterTypes) { | |
- FastClass fastClass = GuiceFastClass.create(clazz); | |
+ FastClass fastClass = codeGen.getFastClass(clazz); | |
final FastConstructor fastConstructor | |
= fastClass.getConstructor(parameterTypes); | |
return new ConstructionProxy<T>() { | |
Index: src/com/google/inject/ProxyFactoryBuilder.java | |
=================================================================== | |
--- src/com/google/inject/ProxyFactoryBuilder.java (revision 345) | |
+++ src/com/google/inject/ProxyFactoryBuilder.java (working copy) | |
@@ -16,6 +16,7 @@ | |
package com.google.inject; | |
+import com.google.inject.internal.GuiceCodeGen; | |
import com.google.inject.matcher.Matcher; | |
import java.lang.reflect.Method; | |
import java.util.ArrayList; | |
@@ -52,7 +53,7 @@ | |
/** | |
* Creates a {@code ProxyFactory}. | |
*/ | |
- public ProxyFactory create() { | |
- return new ProxyFactory(new ArrayList<MethodAspect>(methodAspects)); | |
+ public ProxyFactory create(GuiceCodeGen codeGen) { | |
+ return new ProxyFactory(codeGen, new ArrayList<MethodAspect>(methodAspects)); | |
} | |
} | |
Index: src/com/google/inject/ConstructionContext.java | |
=================================================================== | |
--- src/com/google/inject/ConstructionContext.java (revision 345) | |
+++ src/com/google/inject/ConstructionContext.java (working copy) | |
@@ -23,6 +23,8 @@ | |
import java.util.ArrayList; | |
import java.util.List; | |
+import com.google.inject.internal.GuiceCodeGen; | |
+ | |
/** | |
* Context of a dependency construction. Used to manage circular references. | |
* | |
@@ -60,7 +62,7 @@ | |
invocationHandlers = null; | |
} | |
- Object createProxy(Class<?> expectedType) { | |
+ Object createProxy(GuiceCodeGen codeGen, Class<?> expectedType) { | |
// TODO: if I create a proxy which implements all the interfaces of | |
// the implementation type, I'll be able to get away with one proxy | |
// instance (as opposed to one per caller). | |
@@ -80,8 +82,7 @@ | |
= new DelegatingInvocationHandler<T>(); | |
invocationHandlers.add(invocationHandler); | |
- Object object = Proxy.newProxyInstance(expectedType.getClassLoader(), | |
- new Class[] { expectedType }, invocationHandler); | |
+ Object object = codeGen.getProxy(expectedType, invocationHandler); | |
return expectedType.cast(object); | |
} | |
Index: src/com/google/inject/ClassLoaderHook.java | |
=================================================================== | |
--- src/com/google/inject/ClassLoaderHook.java (revision 0) | |
+++ src/com/google/inject/ClassLoaderHook.java (revision 0) | |
@@ -0,0 +1,29 @@ | |
+/** | |
+ * Copyright (C) 2007 Stuart McCulloch. | |
+ * | |
+ * 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; | |
+ | |
+/** | |
+ * Provide classloading interception for Guice enhanced classes and proxies. | |
+ * | |
+ * @author stuart.mcculloch@jayway.net (Stuart McCulloch) | |
+ */ | |
+public interface ClassLoaderHook { | |
+ | |
+ void setInternalLoader(ClassLoader internalLoader); | |
+ | |
+ ClassLoader get(ClassLoader typeLoader); | |
+} | |
Property changes on: src/com/google/inject/ClassLoaderHook.java | |
___________________________________________________________________ | |
Name: svn:eol-style | |
+ native | |
Index: src/com/google/inject/DefaultClassLoaderHook.java | |
=================================================================== | |
--- src/com/google/inject/DefaultClassLoaderHook.java (revision 0) | |
+++ src/com/google/inject/DefaultClassLoaderHook.java (revision 0) | |
@@ -0,0 +1,34 @@ | |
+/** | |
+ * Copyright (C) 2007 Stuart McCulloch. | |
+ * | |
+ * 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; | |
+ | |
+ | |
+/** | |
+ * Default {@link ClassLoaderHook} implementation (no interception). | |
+ * | |
+ * @author stuart.mcculloch@jayway.net (Stuart McCulloch) | |
+ */ | |
+class DefaultClassLoaderHook implements ClassLoaderHook { | |
+ | |
+ public void setInternalLoader(ClassLoader internalLoader) { | |
+ /* not interested */ | |
+ } | |
+ | |
+ public ClassLoader get(ClassLoader typeLoader) { | |
+ return typeLoader; | |
+ } | |
+} | |
Property changes on: src/com/google/inject/DefaultClassLoaderHook.java | |
___________________________________________________________________ | |
Name: svn:eol-style | |
+ native | |
Index: src/com/google/inject/BinderImpl.java | |
=================================================================== | |
--- src/com/google/inject/BinderImpl.java (revision 345) | |
+++ src/com/google/inject/BinderImpl.java (working copy) | |
@@ -20,6 +20,8 @@ | |
import static com.google.inject.Scopes.SINGLETON; | |
import com.google.inject.internal.Annotations; | |
import static com.google.inject.internal.Objects.nonNull; | |
+ | |
+import com.google.inject.internal.GuiceCodeGen; | |
import com.google.inject.internal.StackTraceElements; | |
import com.google.inject.internal.Stopwatch; | |
import com.google.inject.matcher.Matcher; | |
@@ -241,11 +243,27 @@ | |
* @throws IllegalStateException if called more than once | |
*/ | |
Injector createInjector() throws CreationException { | |
+ return createInjector(new DefaultClassLoaderHook()); | |
+ } | |
+ | |
+ /** | |
+ * Creates a {@link Injector} instance. Injects static members for classes | |
+ * which were registered using {@link #requestStaticInjection(Class...)}. | |
+ * Also registers a classloading hook for enhanced classes and proxies. | |
+ * | |
+ * @throws CreationException if configuration errors are found. The | |
+ * expectation is that the application will log this exception and exit. | |
+ * @throws IllegalStateException if called more than once | |
+ */ | |
+ Injector createInjector(ClassLoaderHook classLoaderHook) throws CreationException { | |
stopwatch.resetAndLog(logger, "Configuration"); | |
+ classLoaderHook.setInternalLoader(getClass().getClassLoader()); | |
+ GuiceCodeGen codeGen = new GuiceCodeGen(classLoaderHook); | |
+ | |
Map<Key<?>, BindingImpl<?>> bindings = new HashMap<Key<?>, BindingImpl<?>>(); | |
injector = new InjectorImpl( | |
- proxyFactoryBuilder.create(), bindings, scopes); | |
+ codeGen, proxyFactoryBuilder.create(codeGen), bindings, scopes); | |
injector.setErrorHandler(configurationErrorHandler); | |
createConstantBindings(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment