📄 injectorimpl.java
字号:
public <T> Provider<T> getProvider(Class<T> type) { return getProvider(Key.get(type)); } public <T> Provider<T> getProvider(final Key<T> key) { final InternalFactory<? extends T> factory = getInternalFactory(null, key); if (factory == null) { throw new ConfigurationException( "Missing binding to " + ErrorMessages.convert(key) + "."); } return new Provider<T>() { public T get() { return callInContext(new ContextualCallable<T>() { public T call(InternalContext context) { ExternalContext<?> previous = context.getExternalContext(); context.setExternalContext( ExternalContext.newInstance(null, key, InjectorImpl.this)); try { return factory.get(context); } finally { context.setExternalContext(previous); } } }); } public String toString() { return factory.toString(); } }; } public <T> T getInstance(Key<T> key) { return getProvider(key).get(); } public <T> T getInstance(Class<T> type) { return getProvider(type).get(); } final ThreadLocal<InternalContext[]> localContext = new ThreadLocal<InternalContext[]>() { protected InternalContext[] initialValue() { return new InternalContext[1]; } }; /** * Looks up thread local context. Creates (and removes) a new context if * necessary. */ <T> T callInContext(ContextualCallable<T> callable) { InternalContext[] reference = localContext.get(); if (reference[0] == null) { reference[0] = new InternalContext(this); try { return callable.call(reference[0]); } finally { // Only remove the context if this call created it. reference[0] = null; } } else { // Someone else will clean up this context. return callable.call(reference[0]); } } /** * Gets a constructor function for a given implementation class. */ @SuppressWarnings("unchecked") <T> ConstructorInjector<T> getConstructor(Class<T> implementation) { return constructors.get(implementation); } @SuppressWarnings("unchecked") <T> ConstructorInjector<T> getConstructor(TypeLiteral<T> implementation) { return constructors.get(implementation.getRawType()); } /** * Injects a field or method in a given object. */ interface SingleMemberInjector { void inject(InternalContext context, Object o); } class MissingDependencyException extends Exception { final Key<?> key; final Member member; MissingDependencyException(Key<?> key, Member member) { this.key = key; this.member = member; } void handle(ErrorHandler errorHandler) { ErrorMessages.handleMissingBinding(errorHandler, member, key, getNamesOfBindingAnnotations(key.getTypeLiteral())); } } /** * Map of primitive type converters. */ static class PrimitiveConverters extends HashMap<Class<?>, Converter<?>> { PrimitiveConverters() { putParser(int.class); putParser(long.class); putParser(boolean.class); putParser(byte.class); putParser(short.class); putParser(float.class); putParser(double.class); // Character doesn't follow the same pattern. Converter<Character> characterConverter = new Converter<Character>() { public Character convert(Member member, Key<Character> key, String value) throws ConstantConversionException { value = value.trim(); if (value.length() != 1) { throw new ConstantConversionException(member, key, value, "Length != 1."); } return value.charAt(0); } }; put(char.class, characterConverter); put(Character.class, characterConverter); } <T> void putParser(final Class<T> primitive) { try { Class<?> wrapper = PRIMITIVE_COUNTERPARTS.get(primitive); final Method parser = wrapper.getMethod( "parse" + Strings.capitalize(primitive.getName()), String.class); Converter<T> converter = new Converter<T>() { @SuppressWarnings("unchecked") public T convert(Member member, Key<T> key, String value) throws ConstantConversionException { try { return (T) parser.invoke(null, value); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new ConstantConversionException(member, key, value, e.getTargetException()); } } }; put(wrapper, converter); put(primitive, converter); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } } /** * Converts a {@code String} to another type. */ interface Converter<T> { /** * Converts {@code String} value. */ T convert(Member member, Key<T> key, String value) throws ConstantConversionException; } Map<Class<?>, InternalFactory<?>> implicitBindings = new HashMap<Class<?>, InternalFactory<?>>(); /** * Gets a factory for the specified type. Used when an explicit binding * was not made. Uses synchronization here so it's not necessary in the * factory itself. Returns {@code null} if the type isn't injectable. */ <T> InternalFactory<? extends T> getImplicitBinding(Member member, final Class<T> type, Scope scope) { // Look for @DefaultImplementation. ImplementedBy implementedBy = type.getAnnotation(ImplementedBy.class); if (implementedBy != null) { Class<?> implementationType = implementedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper loops? if (implementationType == type) { errorHandler.handle(StackTraceElements.forType(type), ErrorMessages.RECURSIVE_IMPLEMENTATION_TYPE, type); return invalidFactory(); } // Make sure implementationType extends type. if (!type.isAssignableFrom(implementationType)) { errorHandler.handle(StackTraceElements.forType(type), ErrorMessages.NOT_A_SUBTYPE, implementationType, type); return invalidFactory(); } return (InternalFactory<T>) getInternalFactory( member, Key.get(implementationType)); } // Look for @DefaultProvider. ProvidedBy providedBy = type.getAnnotation(ProvidedBy.class); if (providedBy != null) { final Class<? extends Provider<?>> providerType = providedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper loops? if (providerType == type) { errorHandler.handle(StackTraceElements.forType(type), ErrorMessages.RECURSIVE_PROVIDER_TYPE, type); return invalidFactory(); } // TODO: Make sure the provided type extends type. We at least check // the type at runtime below. InternalFactory<? extends Provider<?>> providerFactory = getInternalFactory(member, Key.get(providerType)); Key<? extends Provider<?>> providerKey = Key.get(providerType); return (InternalFactory<T>) new BoundProviderFactory( providerKey, providerFactory, StackTraceElements.forType(type)) { public Object get(InternalContext context) { Object o = super.get(context); try { return type.cast(o); } catch (ClassCastException e) { errorHandler.handle(StackTraceElements.forType(type), ErrorMessages.SUBTYPE_NOT_PROVIDED, providerType, type); throw new AssertionError(); } } }; } // TODO: Method interceptors could actually enable us to implement // abstract types. Should we remove this restriction? if (Modifier.isAbstract(type.getModifiers())) { return null; } // Inject the class itself. synchronized (implicitBindings) { @SuppressWarnings("unchecked") InternalFactory<T> factory = (InternalFactory<T>) implicitBindings.get(type); if (factory != null) { return factory; } // Create the factory. ImplicitBinding<T> implicitBinding = new ImplicitBinding<T>(type); // Scope the factory if necessary. // If we don't have a scope from the configuration, look for one on // the type. if (scope == null) { scope = Scopes.getScopeForType(type, scopes, errorHandler); } InternalFactory<? extends T> scoped; if (scope != null) { scoped = Scopes.scope(Key.get(type), this, implicitBinding, scope); } else { scoped = implicitBinding; } implicitBindings.put(type, scoped); try { // Look up the constructor. We do this separately from constructions to // support circular dependencies. ConstructorInjector<T> constructor = getConstructor(type); implicitBinding.setConstructorInjector(constructor); } catch (RuntimeException e) { // Clean up state. implicitBindings.remove(type); throw e; } catch (Throwable t) { // Clean up state. implicitBindings.remove(type); throw new AssertionError(t); } return scoped; } } static class ImplicitBinding<T> implements InternalFactory<T> { final Class<T> implementation; ConstructorInjector<T> constructorInjector; ImplicitBinding(Class<T> implementation) { this.implementation = implementation; } void setConstructorInjector( ConstructorInjector<T> constructorInjector) { this.constructorInjector = constructorInjector; } public T get(InternalContext context) { return (T) constructorInjector.construct(context, context.getExpectedType()); } } private static final InternalFactory<?> INVALID_FACTORY = new InternalFactory<Object>() { public Object get(InternalContext context) { throw new AssertionError(); } }; @SuppressWarnings("unchecked") static <T> InternalFactory<T> invalidFactory() { return (InternalFactory<T>) INVALID_FACTORY; } public String toString() { return new ToStringBuilder(Injector.class) .add("bindings", bindings) .toString(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -