private MetaClass addFactoryDeclaration(final Injectable injectable, final IOCProcessingContext processingContext) { final String factoryName = injectable.getFactoryName(); final MetaClass typeCreatedByFactory = injectable.getInjectedType(); return addFactoryDeclaration(factoryName, typeCreatedByFactory, processingContext); }
private void removeUnreachableInjectables(final ReachabilityStrategy strategy) { logger.debug("Removing unreachable injectables from dependency graph using {} strategy.", strategy); final Set<String> reachableNames = new HashSet<>(); final Queue<Injectable> processingQueue = new LinkedList<>(); final Predicate<Injectable> reachabilityRoot = reachabilityRootPredicate(strategy); for (final Injectable injectable : injectablesByName.values()) { if (reachabilityRoot.test(injectable) && !reachableNames.contains(injectable.getFactoryName()) && !InjectableType.Disabled.equals(injectable.getInjectableType())) { processingQueue.add(injectable); do { final Injectable processedInjectable = processingQueue.poll(); reachableNames.add(processedInjectable.getFactoryName()); logger.trace("Marked as reachable: {}", processedInjectable); for (final Dependency dep : processedInjectable.getDependencies()) { final Injectable resolvedDep = GraphUtil.getResolvedDependency(dep, processedInjectable); if (!reachableNames.contains(resolvedDep.getFactoryName())) { processingQueue.add(resolvedDep); } } } while (processingQueue.size() > 0); } } final int initialSize = injectablesByName.size(); injectablesByName.keySet().retainAll(reachableNames); logger.debug("Removed {} unreachable injectables.", initialSize - injectablesByName.size()); }
private void resolveDependencies() { logger.debug("Resolving dependencies for {} injectables...", injectablesByName.size()); final Set<Injectable> visited = new HashSet<>(); final Set<String> transientInjectableNames = new HashSet<>(); final List<String> dependencyProblems = new ArrayList<>(); final Map<String, Injectable> customProvidedInjectables = new IdentityHashMap<>(); for (final Injectable injectable : injectablesByName.values()) { if (injectable.isExtension()) { transientInjectableNames.add(injectable.getFactoryName()); } if (!visited.contains(injectable)) { logger.debug("Resolving {} dependencies for: {}", injectable.getDependencies().size(), injectable); for (final Dependency dep : injectable.getDependencies()) { resolveDependency(BaseDependency.as(dep), injectable, dependencyProblems, customProvidedInjectables); } } } injectablesByName.keySet().removeAll(transientInjectableNames); injectablesByName.putAll(customProvidedInjectables); if (!dependencyProblems.isEmpty()) { throw new RuntimeException(GraphUtil.buildMessageFromProblems(dependencyProblems)); } }
private Injectable maybeProcessAsExtension(final BaseDependency dep, final Injectable depOwner, final Map<String, Injectable> customProvidedInjectables, final Multimap<ResolutionPriority, InjectableImpl> resolvedByPriority, final Collection<InjectableImpl> resolved) { Injectable injectable = resolved.iterator().next(); if (injectable.isExtension()) { final ExtensionInjectable providedInjectable = (ExtensionInjectable) injectable; final Collection<Injectable> otherResolvedInjectables = new ArrayList<>(resolvedByPriority.values()); otherResolvedInjectables.remove(injectable); final InjectionSite site = new InjectionSite(depOwner.getInjectedType(), dep, otherResolvedInjectables); injectable = providedInjectable.provider.getInjectable(site, nameGenerator); customProvidedInjectables.put(injectable.getFactoryName(), injectable); dep.injectable = GraphUtil.copyInjectableReference(dep.injectable); } return injectable; }
protected ContextualStatementBuilder lookupProviderStmt(final Injectable providerInjectable, final MetaClass paramterizedProviderType) { final ContextualStatementBuilder provider = castTo(paramterizedProviderType, loadVariable("contextManager").invoke("getInstance", loadLiteral(providerInjectable.getFactoryName()))); return provider; }
private Statement initializeProxyHelper(final Injectable injectable) { return newObject( parameterizedAs(ProxyHelperImpl.class, typeParametersOf(injectable.getInjectedType())), injectable.getFactoryName()); }
private void registerAsyncFactory(final Injectable injectable, final IOCProcessingContext processingContext, @SuppressWarnings("rawtypes") final BlockBuilder curMethod, final MetaClass factoryClass) { final Statement handle = generateFactoryHandle(injectable, curMethod); final Statement loader = generateFactoryLoader(injectable, factoryClass); curMethod.append(loadVariable("asyncBeanManagerSetup").invoke("registerAsyncBean", handle, loader)); for (final Dependency dep : injectable.getDependencies()) { if (dep.getInjectable().loadAsync()) { curMethod.append(loadVariable("asyncBeanManagerSetup").invoke("registerAsyncDependency", injectable.getFactoryName(), dep.getInjectable().getFactoryName())); } } }
private List<Statement> methodCreateInstanceStatements(final MetaMethod producingMember, final Injectable producerInjectable, final Injectable producedInjectable, final Collection<Dependency> paramDeps, final ClassStructureBuilder<?> bodyBlockBuilder) { final List<Statement> stmts = new ArrayList<>(); controller.ensureMemberExposed(producingMember); if (!producingMember.isStatic()) { final Statement producerInstanceValue = loadVariable("contextManager").invoke("getInstance", producerInjectable.getFactoryName()); stmts.add(declareVariable(PRODUCER_INSTANCE, producerInjectable.getInjectedType(), producerInstanceValue)); stmts.add(loadVariable(PRODUCER_INSTANCE).assignValue(castTo(producerInjectable.getInjectedType(), invokeStatic(Factory.class, "maybeUnwrapProxy", loadVariable(PRODUCER_INSTANCE))))); } final List<Statement> depScopeRegistrationStmts = new ArrayList<>(); final Statement[] producerParams = generateProducerParams(producingMember, paramDeps, stmts, depScopeRegistrationStmts); final Statement invocation = controller.exposedMethodStmt(loadVariable(PRODUCER_INSTANCE), producingMember, producerParams); stmts.add(declareFinalVariable("instance", producedInjectable.getInjectedType(), invocation)); if (!producingMember.isStatic()) { stmts.add(setProducerInstanceReference()); if (producerInjectable.getWiringElementTypes().contains(WiringElementType.DependentBean)) { stmts.add(loadVariable("this").invoke("registerDependentScopedReference", loadVariable("instance"), loadVariable(PRODUCER_INSTANCE))); } } stmts.addAll(depScopeRegistrationStmts); stmts.add(loadVariable("instance").returnValue()); return stmts; }
private ContextualStatementBuilder getInjectedValue(final Injectable depInjectable, final ParamDependency paramDep) { final ContextualStatementBuilder injectedValue; if (depInjectable.isContextual()) { final MetaClass[] typeArgsClasses = getTypeArguments(paramDep.getParameter().getType()); final Annotation[] qualifiers = getQualifiers(paramDep.getParameter()).toArray(new Annotation[0]); injectedValue = castTo(depInjectable.getInjectedType(), loadVariable("contextManager").invoke("getContextualInstance", loadLiteral(depInjectable.getFactoryName()), typeArgsClasses, qualifiers)); } else { injectedValue = castTo(depInjectable.getInjectedType(), loadVariable("contextManager").invoke("getInstance", loadLiteral(depInjectable.getFactoryName()))); } return injectedValue; } }
private List<Statement> fieldCreateInstanceStatements(final MetaField producingMember, final Injectable producerInjectable, final Injectable producedInjectable, final ClassStructureBuilder<?> bodyBlockBuilder) { final List<Statement> stmts = new ArrayList<>(); controller.ensureMemberExposed(producingMember); if (!producingMember.isStatic()) { final Statement producerInstanceValue = loadVariable("contextManager").invoke("getInstance", producerInjectable.getFactoryName()); stmts.add(declareVariable(PRODUCER_INSTANCE, producerInjectable.getInjectedType(), producerInstanceValue)); stmts.add(loadVariable(PRODUCER_INSTANCE).assignValue(Stmt.castTo(producerInjectable.getInjectedType(), invokeStatic(Factory.class, "maybeUnwrapProxy", loadVariable(PRODUCER_INSTANCE))))); } final Statement invocation = controller.exposedFieldStmt(loadVariable(PRODUCER_INSTANCE), producingMember); stmts.add(declareFinalVariable("instance", producedInjectable.getInjectedType(), invocation)); if (!producingMember.isStatic()) { stmts.add(setProducerInstanceReference()); if (producerInjectable.getWiringElementTypes().contains(WiringElementType.DependentBean)) { stmts.add(loadVariable("this").invoke("registerDependentScopedReference", loadVariable("instance"), loadVariable(PRODUCER_INSTANCE))); } } stmts.add(loadVariable("instance").returnValue()); return stmts; }
private ContextualStatementBuilder generateProducerParamCreationStmt(final ParamDependency paramDep) { ContextualStatementBuilder producerParamCreationStmt; if (paramDep.getInjectable().isContextual()) { final MetaParameter param = paramDep.getParameter(); final MetaClass[] typeArgs = getTypeArguments(param.getType()); final Annotation[] annotations = param.getAnnotations(); producerParamCreationStmt = castTo(paramDep.getInjectable().getInjectedType(), loadVariable("contextManager").invoke("getContextualInstance", paramDep.getInjectable().getFactoryName(), typeArgs, annotations)); } else { producerParamCreationStmt = castTo(paramDep.getInjectable().getInjectedType(), loadVariable("contextManager").invoke("getInstance", paramDep.getInjectable().getFactoryName())); } return producerParamCreationStmt; }
injectedValue = castTo(depInjectable.getInjectedType(), loadVariable("contextManager").invoke("getContextualInstance", loadLiteral(depInjectable.getFactoryName()), typeArgsClasses, qualifiers)); } else { injectedValue = castTo(depInjectable.getInjectedType(), loadVariable("contextManager").invoke("getInstance", loadLiteral(depInjectable.getFactoryName())));
private Statement[] getDisposerParams(final MetaMethod disposer, final Collection<Dependency> disposerParams, final BuildMetaClass factory) { final Statement[] params = new Statement[disposer.getParameters().length]; for (final Dependency dep : disposerParams) { final ParamDependency paramDep = (ParamDependency) dep; final ContextualStatementBuilder paramInstance = castTo(paramDep.getInjectable().getInjectedType(), loadVariable("contextManager").invoke("getInstance", paramDep.getInjectable().getFactoryName())); final ContextualStatementBuilder paramExpression; if (paramDep.getInjectable().getWiringElementTypes().contains(WiringElementType.DependentBean)) { paramExpression = loadVariable("this").invoke("registerDependentScopedReference", loadVariable("instance"), paramInstance); } else { paramExpression = paramInstance; } params[paramDep.getParamIndex()] = paramExpression; } final MetaParameter disposesParam = disposer.getParametersAnnotatedWith(Disposes.class).get(0); params[disposesParam.getIndex()] = loadVariable("instance"); return params; }
injectedValue = castTo(depInjectable.getInjectedType(), loadVariable("contextManager").invoke("getContextualInstance", loadLiteral(depInjectable.getFactoryName()), typeArgsClasses, qualifiers)); } else { injectedValue = castTo(depInjectable.getInjectedType(), loadVariable("contextManager").invoke("getInstance", loadLiteral(depInjectable.getFactoryName())));
protected Statement generateFactoryHandleStatement(final Injectable injectable) { final Statement newObject; if (injectable.getInjectedType().isAnnotationPresent(ActivatedBy.class)) { final Class<? extends BeanActivator> activatorType = injectable.getInjectedType().getAnnotation(ActivatedBy.class).value(); newObject = newObject(FactoryHandleImpl.class, loadLiteral(injectable.getInjectedType()), injectable.getFactoryName(), injectable.getScope(), isEager(injectable.getInjectedType()), injectable.getBeanName(), !injectable.isContextual(), loadLiteral(activatorType)); } else { newObject = newObject(FactoryHandleImpl.class, loadLiteral(injectable.getInjectedType()), injectable.getFactoryName(), injectable.getScope(), isEager(injectable.getInjectedType()), injectable.getBeanName(), !injectable.isContextual()); } return newObject; }
@Override protected Statement generateFactoryHandleStatement(final Injectable injectable) { final Object[] args; if (injectable.getInjectedType().isAnnotationPresent(ActivatedBy.class)) { final Class<? extends BeanActivator> activatorType = injectable.getInjectedType().getAnnotation(ActivatedBy.class).value(); args = new Object[] { loadLiteral(injectable.getInjectedType()), injectable.getFactoryName(), injectable.getScope(), isEager(injectable.getInjectedType()), injectable.getBeanName(), loadLiteral(false), loadLiteral(activatorType) }; } else { args = new Object[] { loadLiteral(injectable.getInjectedType()), injectable.getFactoryName(), injectable.getScope(), isEager(injectable.getInjectedType()), injectable.getBeanName(), loadLiteral(false) }; } return newObject(FactoryHandleImpl.class, args); }
private Statement generateFactoryHandle(final Injectable injectable, @SuppressWarnings("rawtypes") final BlockBuilder curMethod) { final String handleVarName = "handleFor" + injectable.getFactoryName(); curMethod.append(declareFinalVariable(handleVarName, FactoryHandleImpl.class, ObjectBuilder.newInstanceOf(FactoryHandleImpl.class) .withParameters(loadLiteral(injectable.getInjectedType()), loadLiteral(injectable.getFactoryName()), loadLiteral(injectable.getScope()), loadLiteral(false), loadLiteral(injectable.getBeanName()), loadLiteral(!injectable.isContextual())))); curMethod.append(loadVariable(handleVarName).invoke("setAssignableTypes", getAssignableTypesArrayStmt(injectable))); if (!injectable.getQualifier().isDefaultQualifier()) { curMethod.append(loadVariable(handleVarName).invoke("setQualifiers", getAnnotationArrayStmt(injectable.getQualifier()))); } return loadVariable(handleVarName); }
if (requiresProxy && injectedType.isInterface()) { proxyImpl = ClassBuilder .define(injectable.getFactoryName() + "ProxyImpl") .privateScope() .implementsInterface(parameterizedAs(Proxy.class, typeParametersOf(injectedType))) } else if (requiresProxy && isProxiableClass(injectable)) { proxyImpl = ClassBuilder .define(injectable.getFactoryName() + "ProxyImpl", injectedType) .privateScope() .implementsInterface(parameterizedAs(Proxy.class, typeParametersOf(injectedType))).body();
@Override public void generate(final ClassStructureBuilder<?> bodyBlockBuilder, final Injectable injectable, final DependencyGraph graph, final InjectionContext injectionContext, final TreeLogger logger, final GeneratorContext context) { controller = new FactoryController(injectable.getInjectedType(), injectable.getFactoryName(), bodyBlockBuilder.getClassDefinition()); preGenerationHook(bodyBlockBuilder, injectable, graph, injectionContext); final List<Statement> factoryInitStatements = generateFactoryInitStatements(bodyBlockBuilder, injectable, graph, injectionContext); final List<Statement> createInstanceStatements = generateCreateInstanceStatements(bodyBlockBuilder, injectable, graph, injectionContext); final List<Statement> destroyInstanceStatements = generateDestroyInstanceStatements(bodyBlockBuilder, injectable, graph, injectionContext); final List<Statement> invokePostConstructStatements = generateInvokePostConstructsStatements(bodyBlockBuilder, injectable, graph, injectionContext); implementConstructor(bodyBlockBuilder, injectable); maybeImplementFactoryInit(bodyBlockBuilder, injectable, factoryInitStatements); implementCreateInstance(bodyBlockBuilder, injectable, createInstanceStatements); maybeImplementDestroyInstance(bodyBlockBuilder, injectable, destroyInstanceStatements); maybeImplementInvokePostConstructs(bodyBlockBuilder, injectable, invokePostConstructStatements); maybeImplementCreateProxy(bodyBlockBuilder, injectable); addPrivateAccessors(bodyBlockBuilder); }
private Statement createJsTypeProviderFor(final Injectable injectable) { final MetaClass type = injectable.getInjectedType(); final AnonymousClassStructureBuilder jsTypeProvider = newInstanceOf(parameterizedAs(JsTypeProvider.class, typeParametersOf(type))).extend(); jsTypeProvider .publicOverridesMethod("getInstance") .append(Stmt.castTo(type, loadVariable("contextManager").invoke("getInstance", injectable.getFactoryName())) .returnValue()).finish() .publicOverridesMethod("getName") .append(Stmt.loadLiteral(getBeanName(injectable)).returnValue()) .finish() .publicOverridesMethod("getFactoryName") .append(Stmt.loadLiteral(injectable.getFactoryName()).returnValue()) .finish() .publicOverridesMethod("getQualifiers") .append(Stmt.nestedCall(Stmt.newObject(parameterizedAs(JsArray.class, typeParametersOf(String.class)), Stmt.loadLiteral(AnnotationSerializer.serialize(injectable.getQualifier().iterator())))).returnValue()) .finish(); return jsTypeProvider.finish(); }