📄 injectorimpl.java
字号:
/** * 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;import com.google.inject.spi.SourceProviders;import com.google.inject.util.GuiceFastClass;import com.google.inject.util.Objects;import com.google.inject.util.ReferenceCache;import com.google.inject.util.StackTraceElements;import com.google.inject.util.Strings;import com.google.inject.util.ToStringBuilder;import java.lang.annotation.Annotation;import java.lang.reflect.AccessibleObject;import java.lang.reflect.AnnotatedElement;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Member;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import net.sf.cglib.reflect.FastClass;import net.sf.cglib.reflect.FastMethod;/** * Default {@link Injector} implementation. * * @author crazybob@google.com (Bob Lee) * @see BinderImpl */class InjectorImpl implements Injector { /** * Maps between primitive types and their wrappers and vice versa. */ private static final Map<Class<?>, Class<?>> PRIMITIVE_COUNTERPARTS; static { Map<Class<?>, Class<?>> primitiveToWrapper = new HashMap<Class<?>, Class<?>>() {{ put(int.class, Integer.class); put(long.class, Long.class); put(boolean.class, Boolean.class); put(byte.class, Byte.class); put(short.class, Short.class); put(float.class, Float.class); put(double.class, Double.class); put(char.class, Character.class); }}; Map<Class<?>, Class<?>> counterparts = new HashMap<Class<?>, Class<?>>(); for (Map.Entry<Class<?>, Class<?>> entry : primitiveToWrapper.entrySet()) { Class<?> key = entry.getKey(); Class<?> value = entry.getValue(); counterparts.put(key, value); counterparts.put(value, key); } PRIMITIVE_COUNTERPARTS = Collections.unmodifiableMap(counterparts); } private static final Map<Class<?>, Converter<?>> PRIMITIVE_CONVERTERS = new PrimitiveConverters(); final ConstructionProxyFactory constructionProxyFactory; final Map<Key<?>, BindingImpl<?>> bindings; final BindingsMultimap bindingsMultimap = new BindingsMultimap(); final Map<Class<? extends Annotation>, Scope> scopes; ErrorHandler errorHandler = new InvalidErrorHandler(); Object defaultSource = SourceProviders.UNKNOWN_SOURCE; InjectorImpl(ConstructionProxyFactory constructionProxyFactory, Map<Key<?>, BindingImpl<?>> bindings, Map<Class<? extends Annotation>, Scope> scopes) { this.constructionProxyFactory = constructionProxyFactory; this.bindings = bindings; this.scopes = scopes; } /** * Indexes bindings by type. */ void index() { for (BindingImpl<?> binding : bindings.values()) { index(binding); } } <T> void index(BindingImpl<T> binding) { bindingsMultimap.put(binding.getKey().getTypeLiteral(), binding); } // not test-covered public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) { return Collections.<Binding<T>>unmodifiableList( bindingsMultimap.getAll(type)); } // not test-covered <T> List<String> getNamesOfBindingAnnotations(TypeLiteral<T> type) { List<String> names = new ArrayList<String>(); for (Binding<T> binding : findBindingsByType(type)) { Key<T> key = binding.getKey(); if (!key.hasAnnotationType()) { names.add("[no annotation]"); } else { names.add(key.getAnnotationName()); } } return names; } /** * This is only used during Injector building. */ void withDefaultSource(Object defaultSource, Runnable runnable) { Object previous = this.defaultSource; this.defaultSource = defaultSource; try { runnable.run(); } finally { this.defaultSource = previous; } } void setErrorHandler(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } <T> InternalFactory<? extends T> getInternalFactory( final Member member, Key<T> key) { // TODO: Clean up unchecked type warnings. // Do we have a factory for the specified type and name? BindingImpl<T> binding = getBinding(key); if (binding != null) { return binding.getInternalFactory(); } Class<? super T> rawType = key.getTypeLiteral().getRawType(); // Handle cases where T is a Provider<?>. if (rawType.equals(Provider.class)) { Type providerType = key.getTypeLiteral().getType(); if (!(providerType instanceof ParameterizedType)) { // Raw Provider. return null; } Type entryType = ((ParameterizedType) providerType).getActualTypeArguments()[0]; try { final Provider<?> provider = getProvider(key.ofType(entryType)); return new InternalFactory<T>() { @SuppressWarnings("unchecked") public T get(InternalContext context) { return (T) provider; } }; } catch (ConfigurationException e) { // Look for a factory bound to a key without annotation attributes if // necessary. if (key.hasAttributes()) { return getInternalFactory(member, key.withoutAttributes()); } // End of the road. ErrorMessages.handleMissingBinding(errorHandler, member, key, getNamesOfBindingAnnotations(key.getTypeLiteral())); return invalidFactory(); } } // Auto[un]box primitives. Class<?> primitiveCounterpart = PRIMITIVE_COUNTERPARTS.get(rawType); if (primitiveCounterpart != null) { BindingImpl<?> counterpartBinding = getBinding(key.ofType(primitiveCounterpart)); if (counterpartBinding != null) { return (InternalFactory<? extends T>) counterpartBinding.getInternalFactory(); } } // TODO: Should we try to convert from a String first, or should we look // for a binding to the annotation type sans attributes? Right now, we // convert from a String. // Can we convert from a String constant? Key<String> stringKey = key.ofType(String.class); BindingImpl<String> stringBinding = getBinding(stringKey); if (stringBinding != null && stringBinding.isConstant()) { // We don't need do pass in an InternalContext because we know this is // a ConstantFactory which will not use it. String value = stringBinding.getInternalFactory().get(null); // TODO: Generalize everything below here and enable users to plug in // their own converters. // Do we need a primitive? Converter<T> converter = (Converter<T>) PRIMITIVE_CONVERTERS.get(rawType); if (converter != null) { try { T t = converter.convert(member, key, value); return new ConstantFactory<T>(t); } catch (ConstantConversionException e) { return handleConstantConversionError( member, stringBinding, rawType, e); } } // Do we need an enum? if (Enum.class.isAssignableFrom(rawType)) { T t; try { t = (T) Enum.valueOf((Class) rawType, value); } catch (IllegalArgumentException e) { return handleConstantConversionError( member, stringBinding, rawType, e); } return new ConstantFactory<T>(t); } // Do we need a class? if (rawType == Class.class) { try { // TODO: Make sure we use the right classloader. return new ConstantFactory<T>((T) Class.forName(value)); } catch (ClassNotFoundException e) { return handleConstantConversionError( member, stringBinding, rawType, e); } } } // Don't try to inject primitives, arrays, or enums. int modifiers = rawType.getModifiers(); if (rawType.isArray() || rawType.isEnum() || rawType.isPrimitive()) { // Look for a factory bound to a key without annotation attributes if // necessary. if (key.hasAttributes()) { return getInternalFactory(member, key.withoutAttributes()); } return null; } // We don't want to implicitly inject a member if we have a binding // annotation. if (key.hasAnnotationType()) { // Look for a factory bound to a key without annotation attributes if // necessary. if (key.hasAttributes()) { return getInternalFactory(member, key.withoutAttributes()); } return null; } // Last resort: inject the type itself. if (member != null) { // If we're injecting into a member, include it in the error messages. final ErrorHandler previous = this.errorHandler; this.errorHandler = new AbstractErrorHandler() { public void handle(Object source, String message) { previous.handle(source, "Error while injecting at " + StackTraceElements.forMember(member) + ": " + message); } }; try { // note: intelliJ thinks this cast is superfluous, but is it? return (InternalFactory<? extends T>) getImplicitBinding(member, rawType, null); } finally { this.errorHandler = previous; } } // note: intelliJ thinks this cast is superfluous, but is it? return (InternalFactory<? extends T>) getImplicitBinding(member, rawType, null); } private <T> InternalFactory<T> handleConstantConversionError( Member member, Binding<String> stringBinding, Class<?> rawType, Exception e) { errorHandler.handle( StackTraceElements.forMember(member), ErrorMessages.CONSTANT_CONVERSION_ERROR, stringBinding.getSource(), rawType, e.getMessage()); return invalidFactory(); } /** * Field and method injectors. */ final Map<Class<?>, List<SingleMemberInjector>> injectors = new ReferenceCache<Class<?>, List<SingleMemberInjector>>() { protected List<SingleMemberInjector> create(Class<?> key) { List<SingleMemberInjector> injectors = new ArrayList<SingleMemberInjector>(); addInjectors(key, injectors); return injectors; } }; /** * Recursively adds injectors for fields and methods from the given class to * the given list. Injects parent classes before sub classes. */ void addInjectors(Class clazz, List<SingleMemberInjector> injectors) { if (clazz == Object.class) { return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -