private void addProvidedByConstructionRule() { // rule for @ProvidedBy config.construction.constructionRules .add(new ProvidedByConstructionRuleBase(Provider.class) { @Override protected DependencyKey<?> getProviderKey( TypeToken<?> type) { ProvidedBy providedBy = type.getRawType() .getAnnotation(ProvidedBy.class); if (providedBy != null) { if (!type.isAssignableFrom( TypeToken.of(providedBy.value()) .resolveType(Provider.class .getTypeParameters()[0]))) { throw new SaltaException( "Provider " + providedBy.value() + " specified by @ProvidedBy does not provide " + type); } return DependencyKey.of(providedBy.value()); } return null; } }); }
private BindProviderBinding createProvidedByBinding(Key<?> key, ProvidedBy providedBy) throws BindingCreationException { Class<?> rawType = key.getTypeLiteral().getRawType(); Class<? extends Provider<?>> providerType = providedBy.value(); if (providerType == rawType) { throw new BindingCreationException( "@ProvidedBy points to the same class it annotates: %s", rawType); } return bindingFactory.getBindProviderBinding(Key.get(providerType), key, Context.forText("@ProvidedBy annotation")); }
/** Creates a binding for a type annotated with @ProvidedBy. */ <T> BindingImpl<T> createProvidedByBinding( Key<T> key, Scoping scoping, ProvidedBy providedBy, Errors errors) throws ErrorsException { Class<?> rawType = key.getTypeLiteral().getRawType(); Class<? extends javax.inject.Provider<?>> providerType = providedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper loops? if (providerType == rawType) { throw errors.recursiveProviderType().toException(); } // Assume the provider provides an appropriate type. We double check at runtime. @SuppressWarnings("unchecked") Key<? extends Provider<T>> providerKey = (Key<? extends Provider<T>>) Key.get(providerType); ProvidedByInternalFactory<T> internalFactory = new ProvidedByInternalFactory<T>(rawType, providerType, providerKey); Object source = rawType; BindingImpl<T> binding = LinkedProviderBindingImpl.createWithInitializer( this, key, source, Scoping.<T>scope(key, this, internalFactory, source, scoping), scoping, providerKey, internalFactory); internalFactory.setProvisionListenerCallback(provisionListenerStore.get(binding)); return binding; }
/** Creates a binding for a type annotated with @ProvidedBy. */ <T> BindingImpl<T> createProvidedByBinding(Key<T> key, Scoping scoping, ProvidedBy providedBy, Errors errors) throws ErrorsException { Class<?> rawType = key.getTypeLiteral().getRawType(); Class<? extends Provider<?>> providerType = providedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper loops? if (providerType == rawType) { throw errors.recursiveProviderType().toException(); } // Assume the provider provides an appropriate type. We double check at runtime. @SuppressWarnings("unchecked") Key<? extends Provider<T>> providerKey = (Key<? extends Provider<T>>) Key.get(providerType); ProvidedByInternalFactory<T> internalFactory = new ProvidedByInternalFactory<T>(rawType, providerType, providerKey, !options.disableCircularProxies); Object source = rawType; BindingImpl<T> binding = LinkedProviderBindingImpl.createWithInitializer( this, key, source, Scoping.<T>scope(key, this, internalFactory, source, scoping), scoping, providerKey, internalFactory); internalFactory.setProvisionListenerCallback(provisionListenerStore.get(binding)); return binding; }
/** * Creates the implicit binding */ public Binding create(Key<?> key) throws BindingCreationException { TypeLiteral<?> type = key.getTypeLiteral(); // All steps per: // http://code.google.com/p/google-guice/wiki/BindingResolution // 1. Explicit binding - already finished at this point. // 2. Ask parent injector. // 3. Ask child injector. // These bindings are created in BindingResolver and are not necessary here. // 4. Provider injections. if (isProviderKey(key)) { return bindingFactory.getImplicitProviderBinding(key); // TODO(bstoler): Scope the provider binding like the thing being provided? } // 4b. AsyncProvider injections. if (isAsyncProviderKey(key)) { return bindingFactory.getAsyncProviderBinding(key); } // 5. Convert constants. // Already covered by resolving explicit bindings. if (BindConstantBinding.isConstantKey(key)) { throw new BindingCreationException( "Binding requested for constant key '%s' but no explicit binding was found", key); } // 6. If the dependency has a binding annotation, give up. if (key.getAnnotation() != null || key.getAnnotationType() != null) { throw new BindingCreationException("No implementation bound for '%s' and an implicit binding" + " cannot be created because the type is annotated.", key); } // 7. If the dependency is an array or enum, give up. // Covered by step 5 (enum) and 11 (array). // 8. Handle TypeLiteral injections. // TODO(schmitt): Implement TypeLiteral injections. // 9. Use resolution annotations (@ImplementedBy, @ProvidedBy) ImplementedBy implementedBy = type.getRawType().getAnnotation(ImplementedBy.class); if (implementedBy != null) { return createImplementedByBinding(key, implementedBy); } ProvidedBy providedBy = type.getRawType().getAnnotation(ProvidedBy.class); if (providedBy != null) { return createProvidedByBinding(key, providedBy); } // 10. If the dependency is abstract or a non-static inner class, give up. // Abstract classes are handled by GWT.create. // TODO(schmitt): Introduce check. // 11. Use a single @Inject or public no-arguments constructor. return createImplicitBindingForClass(type); }
/** * Creates a binding for an injectable type with the given scope. Looks for a scope on the type if * none is specified. */ <T> BindingImpl<T> createUninitializedBinding( Key<T> key, Scoping scoping, Object source, Errors errors, boolean jitBinding) throws ErrorsException { Class<?> rawType = key.getTypeLiteral().getRawType(); ImplementedBy implementedBy = rawType.getAnnotation(ImplementedBy.class); // Don't try to inject arrays or enums annotated with @ImplementedBy. if (rawType.isArray() || (rawType.isEnum() && implementedBy != null)) { throw errors.missingImplementationWithHint(key, this).toException(); } // Handle TypeLiteral<T> by binding the inner type if (rawType == TypeLiteral.class) { @SuppressWarnings("unchecked") // we have to fudge the inner type as Object BindingImpl<T> binding = (BindingImpl<T>) createTypeLiteralBinding((Key<TypeLiteral<Object>>) key, errors); return binding; } // Handle @ImplementedBy if (implementedBy != null) { Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors); return createImplementedByBinding(key, scoping, implementedBy, errors); } // Handle @ProvidedBy. ProvidedBy providedBy = rawType.getAnnotation(ProvidedBy.class); if (providedBy != null) { Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors); return createProvidedByBinding(key, scoping, providedBy, errors); } return ConstructorBindingImpl.create( this, key, null, /* use default constructor */ source, scoping, errors, jitBinding && options.jitDisabled, options.atInjectRequired); }
/** * Creates a binding for an injectable type with the given scope. Looks for a scope on the type if * none is specified. */ <T> BindingImpl<T> createUninitializedBinding(Key<T> key, Scoping scoping, Object source, Errors errors, boolean jitBinding) throws ErrorsException { Class<?> rawType = key.getTypeLiteral().getRawType(); // Don't try to inject arrays, or enums. if (rawType.isArray() || rawType.isEnum()) { throw errors.missingImplementation(key).toException(); } // Handle TypeLiteral<T> by binding the inner type if (rawType == TypeLiteral.class) { @SuppressWarnings("unchecked") // we have to fudge the inner type as Object BindingImpl<T> binding = (BindingImpl<T>) createTypeLiteralBinding( (Key<TypeLiteral<Object>>) key, errors); return binding; } // Handle @ImplementedBy ImplementedBy implementedBy = rawType.getAnnotation(ImplementedBy.class); if (implementedBy != null) { Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors); return createImplementedByBinding(key, scoping, implementedBy, errors); } // Handle @ProvidedBy. ProvidedBy providedBy = rawType.getAnnotation(ProvidedBy.class); if (providedBy != null) { Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors); return createProvidedByBinding(key, scoping, providedBy, errors); } return ConstructorBindingImpl.create(this, key, null, /* use default constructor */ source, scoping, errors, jitBinding && options.jitDisabled, options.atInjectRequired); }