@ Override public Object invoke ( Object proxy , final Method method , final Object [ ] args ) throws Throwable { // If we setup a method handle earlier for this method, call it. // This is necessary for default methods that java8 creates, so we // can call the default method implementation (and not our proxied version of it). if ( methodHandleByMethod . containsKey ( method ) ) { return methodHandleByMethod . get ( method ) . invokeWithArguments ( args ) ; } if ( method . getDeclaringClass ( ) . equals ( Object . class ) ) { if ( "equals" . equals ( method . getName ( ) ) ) { return proxy == args [ 0 ] ; } else if ( "hashCode" . equals ( method . getName ( ) ) ) { return System . identityHashCode ( proxy ) ; } else { return method . invoke ( this , args ) ; } } AssistData data = assistDataByMethod . get ( method ) ; checkState ( data != null , "No data for method: %s" , method ) ; Provider < ? > provider ; if ( data . cachedBinding != null ) { // Try to get optimized form... provider = data . cachedBinding . getProvider ( ) ; } else { provider = getBindingFromNewInjector ( method , args , data ) . getProvider ( ) ; } try { int p = 0 ; for ( ThreadLocalProvider tlp : data . providers ) { tlp . set ( args [ p ++ ] ) ; } return provider . get ( ) ; } catch ( ProvisionException e ) { // if this is an exception declared by the factory method, throw it as-is if ( e . getErrorMessages ( ) . size ( ) == 1 ) { Message onlyError = getOnlyElement ( e . getErrorMessages ( ) ) ; Throwable cause = onlyError . getCause ( ) ; if ( cause != null && canRethrow ( method , cause ) ) { throw cause ; } } throw e ; } finally { for ( ThreadLocalProvider tlp : data . providers ) { tlp . remove ( ) ; } } }
When a factory method is invoked we create a child injector that binds all parameters then use that to get an instance of the return type .