@Override public synchronized void configure(Binder binder) { System.out.println("start"); for (ProviderMethod<?> providerMethod : getProviderMethods(binder)) { providerMethod.configure(binder); } }
public List<ProviderMethod<?>> getProviderMethods(Binder binder) { System.out.println("end"); List<ProviderMethod<?>> result = Lists.newArrayList(); Multimap<Signature, Method> methodsBySignature = HashMultimap.create(); for (Class<?> c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) { for (Method method : c.getDeclaredMethods()) { // private/static methods cannot override or be overridden by other methods, so there is no // point in indexing them. // Skip synthetic methods and bridge methods since java will automatically generate // synthetic overrides in some cases where we don't want to generate an error (e.g. // increasing visibility of a subclass). if (((method.getModifiers() & (Modifier.PRIVATE | Modifier.STATIC)) == 0) && !method.isBridge() && !method.isSynthetic()) { methodsBySignature.put(new Signature(method), method); } Optional<Annotation> annotation = isProvider(binder, method); if (annotation.isPresent()) { result.add(createProviderMethod(binder, method, annotation.get())); } } } // we have found all the providers and now need to identify if any were overridden // In the worst case this will have O(n^2) in the number of @Provides methods, but that is only // assuming that every method is an override, in general it should be very quick. for (ProviderMethod<?> provider : result) { Method method = provider.getMethod(); for (Method matchingSignature : methodsBySignature.get(new Signature(method))) { // matching signature is in the same class or a super class, therefore method cannot be // overridding it. if (matchingSignature.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) { continue; } // now we know matching signature is in a subtype of method.getDeclaringClass() if (overrides(matchingSignature, method)) { String annotationString = provider.getAnnotation().annotationType() == Provides.class ? "@Provides" : "@" + provider.getAnnotation().annotationType().getCanonicalName(); binder.addError( "Overriding " + annotationString + " methods is not allowed." + "\n\t" + annotationString + " method: %s\n\toverridden by: %s", method, matchingSignature); break; } } } return result; }
private <T> ProviderMethod<T> createProviderMethod( Binder binder, Method method, Annotation annotation) { binder = binder.withSource(method); Errors errors = new Errors(method); // prepare the parameter providers InjectionPoint point = InjectionPoint.forMethod(method, typeLiteral); List<Dependency<?>> dependencies = point.getDependencies(); List<Provider<?>> parameterProviders = Lists.newArrayList(); for (Dependency<?> dependency : point.getDependencies()) { parameterProviders.add(binder.getProvider(dependency)); } @SuppressWarnings("unchecked") // Define T as the method's return type. TypeLiteral<T> returnType = (TypeLiteral<T>) typeLiteral.getReturnType(method); Key<T> key = getKey(errors, returnType, method, method.getAnnotations()); try { key = scanner.prepareMethod(binder, annotation, key, point); } catch (Throwable t) { binder.addError(t); } Class<? extends Annotation> scopeAnnotation = Annotations.findScopeAnnotation(errors, method.getAnnotations()); for (Message message : errors.getMessages()) { binder.addError(message); } return ProviderMethod.create( key, method, delegate, ImmutableSet.copyOf(dependencies), parameterProviders, scopeAnnotation, skipFastClassGeneration, annotation); }