private void addImplementedByConstructionRule() { // rule for @ImplementedBy config.construction.constructionRules .add(new ImplementedByConstructionRuleBase() { @Override protected DependencyKey<?> getImplementorKey( TypeToken<?> type) { ImplementedBy implementedBy = type.getRawType() .getAnnotation(ImplementedBy.class); if (implementedBy != null) { if (type.getRawType() .equals(implementedBy.value())) { throw new SaltaException( "@ImplementedBy points to the same class it annotates. type: " + type); } return DependencyKey.of(implementedBy.value()); } return null; } }); }
private BindClassBinding createImplementedByBinding(Key<?> key, ImplementedBy implementedBy) throws BindingCreationException { Class<?> rawType = key.getTypeLiteral().getRawType(); Class<?> implementationType = implementedBy.value(); if (implementationType == rawType) { throw new BindingCreationException( "@ImplementedBy points to the same class it annotates: %s", rawType); } if (!rawType.isAssignableFrom(implementationType)) { throw new BindingCreationException("%s doesn't extend %s (while resolving @ImplementedBy)", implementationType, rawType); } return bindingFactory.getBindClassBinding(Key.get(implementationType), key, Context.forText("@ImplementedBy annotation")); }
@Override protected void configure() { final ImplementedBy implementedBy = type.getRawType().getAnnotation(ImplementedBy.class); bind(parserKey).toInstance(new ReflectiveParserImpl( implementedBy != null ? implementedBy.value() : this.baseClass, Members.annotations(Parseable.Property.class, Methods.declaredMethodsInAncestors(type.getRawType())) .merge(this::createProperty) .collect(Collectors.toImmutableList()) )); }
/** Creates a binding for a type annotated with @ImplementedBy. */ private <T> BindingImpl<T> createImplementedByBinding( Key<T> key, Scoping scoping, ImplementedBy implementedBy, Errors errors) throws ErrorsException { Class<?> rawType = key.getTypeLiteral().getRawType(); Class<?> implementationType = implementedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper cycles? if (implementationType == rawType) { throw errors.recursiveImplementationType().toException(); } // Make sure implementationType extends type. if (!rawType.isAssignableFrom(implementationType)) { throw errors.notASubtype(implementationType, rawType).toException(); } @SuppressWarnings("unchecked") // After the preceding check, this cast is safe. Class<? extends T> subclass = (Class<? extends T>) implementationType; // Look up the target binding. final Key<? extends T> targetKey = Key.get(subclass); Object source = rawType; FactoryProxy<T> factory = new FactoryProxy<>(this, key, targetKey, source); factory.notify(errors); // causes the factory to initialize itself internally return new LinkedBindingImpl<T>( this, key, source, Scoping.<T>scope(key, this, factory, source, scoping), scoping, targetKey); }
/** * 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); }
private <T> void autobind(Class<T> clazz) { // If the class is a regular class (or an interface annotated with @ImplementedBy)... if (!clazz.isInterface() || clazz.isAnnotationPresent(ImplementedBy.class)) { // Guice knows how to bind this already so no need to search for an implementation, just expose it via JAX-RS RestResourceRegistry.register(clazz); } else { // Search for implementations final List<Class<? extends T>> implementations = scannerFactory.getInstance().getImplementations(clazz); if (implementations.size() == 1) { RestResourceRegistry.register(clazz); bind(clazz).to(implementations.get(0)); } else if (implementations.size() == 0) { if (ResteasyProxyClientFactoryImpl.getConfiguredBoundServiceName(config, clazz) != null) { log.debug( "Found JAX-RS interface with no implementation but a service.{name}.endpoint config. Auto-binding a client: " + clazz); TypeLiteral typeLiteral = TypeLiteral.<JAXRSClientProvider<T>>get(Types.newParameterizedType( JAXRSClientProvider.class, clazz)); bind(clazz).toProvider(typeLiteral); } else { log.debug("Found JAX-RS interface with no implementation and no service.{name}.endpoint config. Ignoring: " + clazz); } } else { // Too many interfaces throw new IllegalArgumentException("Expected 0 or 1 implementation for auto-discovered REST interface " + clazz + " but found " + implementations + ". Auto-binding REST interfaces is not possible."); } } }