📄 injectorimpl.java
字号:
} // Add injectors for superclass first. addInjectors(clazz.getSuperclass(), injectors); // TODO (crazybob): Filter out overridden members. addSingleInjectorsForFields(clazz.getDeclaredFields(), false, injectors); addSingleInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors); } void addSingleInjectorsForMethods(Method[] methods, boolean statics, List<SingleMemberInjector> injectors) { addInjectorsForMembers(Arrays.asList(methods), statics, injectors, new SingleInjectorFactory<Method>() { public SingleMemberInjector create(InjectorImpl injector, Method method) throws MissingDependencyException { return new SingleMethodInjector(injector, method); } }); } void addSingleInjectorsForFields(Field[] fields, boolean statics, List<SingleMemberInjector> injectors) { addInjectorsForMembers(Arrays.asList(fields), statics, injectors, new SingleInjectorFactory<Field>() { public SingleMemberInjector create(InjectorImpl injector, Field field) throws MissingDependencyException { return new SingleFieldInjector(injector, field); } }); } <M extends Member & AnnotatedElement> void addInjectorsForMembers( List<M> members, boolean statics, List<SingleMemberInjector> injectors, SingleInjectorFactory<M> injectorFactory) { for (M member : members) { if (isStatic(member) == statics) { Inject inject = member.getAnnotation(Inject.class); if (inject != null) { try { injectors.add(injectorFactory.create(this, member)); } catch (MissingDependencyException e) { if (!inject.optional()) { // TODO: Report errors for more than one parameter per member. e.handle(errorHandler); } } } } } } Map<Key<?>, BindingImpl<?>> internalBindings() { return bindings; } // not test-covered public Map<Key<?>, Binding<?>> getBindings() { return Collections.<Key<?>, Binding<?>>unmodifiableMap(bindings); } @SuppressWarnings("unchecked") public <T> BindingImpl<T> getBinding(Key<T> key) { return (BindingImpl<T>) bindings.get(key); } interface SingleInjectorFactory<M extends Member & AnnotatedElement> { SingleMemberInjector create(InjectorImpl injector, M member) throws MissingDependencyException; } private boolean isStatic(Member member) { return Modifier.isStatic(member.getModifiers()); } private static class BindingsMultimap { private final Map<TypeLiteral<?>, List<? extends BindingImpl<?>>> map = new HashMap<TypeLiteral<?>, List<? extends BindingImpl<?>>>(); public <T> void put(TypeLiteral<T> type, BindingImpl<T> binding) { List<BindingImpl<T>> bindingsForThisType = getFromMap(type); if (bindingsForThisType == null) { bindingsForThisType = new ArrayList<BindingImpl<T>>(); // We only put matching entries into the map map.put(type, bindingsForThisType); } bindingsForThisType.add(binding); } public <T> List<BindingImpl<T>> getAll(TypeLiteral<T> type) { List<BindingImpl<T>> list = getFromMap(type); return list == null ? Collections.<BindingImpl<T>>emptyList() : list; } // safe because we only put matching entries into the map @SuppressWarnings("unchecked") private <T> List<BindingImpl<T>> getFromMap(TypeLiteral<T> type) { return (List<BindingImpl<T>>) map.get(type); } } class SingleFieldInjector implements SingleMemberInjector { final Field field; final InternalFactory<?> factory; final ExternalContext<?> externalContext; public SingleFieldInjector(InjectorImpl injector, Field field) throws MissingDependencyException { this.field = field; // Ewwwww... field.setAccessible(true); Key<?> key = Key.get( field.getGenericType(), field, field.getAnnotations(), errorHandler); factory = injector.getInternalFactory(field, key); if (factory == null) { throw new MissingDependencyException(key, field); } this.externalContext = ExternalContext.newInstance(field, key, injector); } public void inject(InternalContext context, Object o) { ExternalContext<?> previous = context.getExternalContext(); context.setExternalContext(externalContext); try { Object value = factory.get(context); if (value == null) { throw new AssertionError(); // we should have prevented this } field.set(o, value); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (ConfigurationException e) { throw e; } catch (Throwable throwable) { throw new ProvisionException(externalContext, throwable); } finally { context.setExternalContext(previous); } } } /** * Gets parameter injectors. * * @param member to which the parameters belong * @param annotations on the parameters * @param parameterTypes parameter types * @return injections */ <M extends AccessibleObject & Member> SingleParameterInjector<?>[] getParametersInjectors(M member, Annotation[][] annotations, Type[] parameterTypes) throws MissingDependencyException { SingleParameterInjector<?>[] parameterInjectors = new SingleParameterInjector<?>[parameterTypes.length]; Iterator<Annotation[]> annotationsIterator = Arrays.asList(annotations).iterator(); int index = 0; for (Type parameterType : parameterTypes) { Annotation[] parameterAnnotations = annotationsIterator.next(); Key<?> key = Key.get( parameterType, member, parameterAnnotations, errorHandler); parameterInjectors[index] = createParameterInjector(key, member, index); index++; } return parameterInjectors; } <T> SingleParameterInjector<T> createParameterInjector( Key<T> key, Member member, int index) throws MissingDependencyException { InternalFactory<? extends T> factory = getInternalFactory(member, key); if (factory == null) { throw new MissingDependencyException(key, member); } ExternalContext<T> externalContext = ExternalContext.newInstance(member, index, key, this); return new SingleParameterInjector<T>(externalContext, factory); } static class SingleMethodInjector implements SingleMemberInjector { final MethodInvoker methodInvoker; final SingleParameterInjector<?>[] parameterInjectors; public SingleMethodInjector(InjectorImpl injector, final Method method) throws MissingDependencyException { // We can't use FastMethod if the method is private. if (Modifier.isPrivate(method.getModifiers()) || Modifier.isProtected(method.getModifiers())) { method.setAccessible(true); this.methodInvoker = new MethodInvoker() { public Object invoke(Object target, Object... parameters) throws IllegalAccessException, InvocationTargetException { Objects.assertNoNulls(parameters); return method.invoke(target, parameters); } }; } else { FastClass fastClass = GuiceFastClass.create(method.getDeclaringClass()); final FastMethod fastMethod = fastClass.getMethod(method); this.methodInvoker = new MethodInvoker() { public Object invoke(Object target, Object... parameters) throws IllegalAccessException, InvocationTargetException { Objects.assertNoNulls(parameters); return fastMethod.invoke(target, parameters); } }; } Type[] parameterTypes = method.getGenericParameterTypes(); parameterInjectors = parameterTypes.length > 0 ? injector.getParametersInjectors( method, method.getParameterAnnotations(), parameterTypes) : null; } public void inject(InternalContext context, Object o) { try { methodInvoker.invoke(o, getParameters(context, parameterInjectors)); } catch (Exception e) { throw new RuntimeException(e); } } } /** * Invokes a method. */ interface MethodInvoker { Object invoke(Object target, Object... parameters) throws IllegalAccessException, InvocationTargetException; } final Map<Class<?>, ConstructorInjector> constructors = new ReferenceCache<Class<?>, ConstructorInjector>() { @SuppressWarnings("unchecked") protected ConstructorInjector<?> create(Class<?> implementation) { if (implementation.isInterface()) { errorHandler.handle(defaultSource, ErrorMessages.CANNOT_INJECT_ABSTRACT_TYPE, implementation); return ConstructorInjector.invalidConstructor(); } return new ConstructorInjector(InjectorImpl.this, implementation); } }; /** * A placeholder. This enables us to continue processing and gather more * errors but blows up if you actually try to use it. */ static class InvalidConstructor { InvalidConstructor() { throw new AssertionError(); } } @SuppressWarnings("unchecked") static <T> Constructor<T> invalidConstructor() { try { return (Constructor<T>) InvalidConstructor.class.getDeclaredConstructor(); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } static class SingleParameterInjector<T> { final ExternalContext<T> externalContext; final InternalFactory<? extends T> factory; public SingleParameterInjector(ExternalContext<T> externalContext, InternalFactory<? extends T> factory) { this.externalContext = externalContext; this.factory = factory; } T inject(InternalContext context) { ExternalContext<?> previous = context.getExternalContext(); context.setExternalContext(externalContext); try { return factory.get(context); } catch (ConfigurationException e) { throw e; } catch (Throwable throwable) { throw new ProvisionException(externalContext, throwable); } finally { context.setExternalContext(previous); } } } /** * Iterates over parameter injectors and creates an array of parameter * values. */ static Object[] getParameters(InternalContext context, SingleParameterInjector[] parameterInjectors) { if (parameterInjectors == null) { return null; } Object[] parameters = new Object[parameterInjectors.length]; for (int i = 0; i < parameters.length; i++) { parameters[i] = parameterInjectors[i].inject(context); } return parameters; } void injectMembers(Object o, InternalContext context) { List<SingleMemberInjector> injectorsForClass = injectors.get(o.getClass()); for (SingleMemberInjector injector : injectorsForClass) { injector.inject(context, o); } } // Not test-covered public void injectMembers(final Object o) { callInContext(new ContextualCallable<Void>() { public Void call(InternalContext context) { injectMembers(o, context); return null; } }); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -