*/
return loadVariable(creationalCallbackVarName).invoke("getInstance", Refs.get("context"));
}
}
final InjectionContext injectContext = injectableInstance.getInjectionContext();
final IOCProcessingContext ctx = injectContext.getProcessingContext();
/*
get a parameterized version of the CreationalCallback class, parameterized with the type of
bean it produces.
*/
final MetaClass creationCallbackRef = parameterizedAs(CreationalCallback.class, typeParametersOf(type));
/*
begin building the creational callback, implement the "getInstance" method from the interface
and assign its BlockBuilder to a callbackBuilder so we can work with it.
*/
final BlockBuilder<AnonymousClassStructureBuilder> callbackBuilder
= newInstanceOf(creationCallbackRef).extend()
.publicOverridesMethod("getInstance", Parameter.of(CreationalContext.class, "context", true));
/* push the method block builder onto the stack, so injection tasks are rendered appropriately. */
ctx.pushBlockBuilder(callbackBuilder);
/* get a new unique variable for the creational callback */
creationalCallbackVarName = InjectUtil.getNewInjectorName().concat("_")
.concat(type.getName()).concat("_creational");
/* get the construction strategy and execute it to wire the bean */
getConstructionStrategy(this, injectContext).generateConstructor(new ConstructionStatusCallback() {
@Override
public void beanConstructed() {
/* the bean has been constructed, so get a reference to the BeanRef and set it to the 'beanRef' variable. */
/* add the bean to CreationalContext */
callbackBuilder.append(
loadVariable("context").invoke("addBean", loadVariable("context").invoke("getBeanReference", load(type),
load(qualifyingMetadata.getQualifiers())), Refs.get(instanceVarName))
);
/* mark this injector as injected so we don't go into a loop if there is a cycle. */
setCreated(true);
}
});
/*
return the instance of the bean from the creational callback.
*/
callbackBuilder.append(loadVariable(instanceVarName).returnValue());
/* pop the block builder of the stack now that we're done wiring. */
ctx.popBlockBuilder();
/*
declare a final variable for the CreationalCallback and initialize it with the anonymous class we just
built.
*/
ctx.getBootstrapBuilder().privateField(creationalCallbackVarName, creationCallbackRef).modifiers(Modifier.Final)
.initializesWith(callbackBuilder.finish().finish()).finish();
final Statement retVal;
if (isSingleton()) {
/*
if the injector is for a singleton, we create a variable to hold the singleton reference in the bootstrapper
method and assign it with CreationalContext.getInstance().
*/
ctx.getBootstrapBuilder().privateField(instanceVarName, type).modifiers(Modifier.Final)
.initializesWith(loadVariable(creationalCallbackVarName).invoke("getInstance", Refs.get("context"))).finish();
/*
use the variable we just assigned as the return value for this injector.
*/
retVal = Refs.get(instanceVarName);
}
else {
/*
the injector is a dependent scope, so use CreationContext.getInstance() as the return value.
*/
retVal = loadVariable(creationalCallbackVarName).invoke("getInstance", Refs.get("context"));
}
setRendered(true);
markRendered(injectableInstance);
/*
notify any component waiting for this type that is is ready now.
*/
injectableInstance.getInjectionContext().getProcessingContext()
.handleDiscoveryOfType(injectableInstance);
injectContext.markProxyClosedIfNeeded(getInjectedType(), getQualifyingMetadata());
/*
return the reference to this bean to whoever called us.
*/
return retVal;
}