Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package io.fairyproject.container;

import io.fairyproject.container.type.TypeDescriptor;
import lombok.experimental.UtilityClass;

/**
Expand All @@ -39,5 +40,9 @@ public <T> T get(Class<T> type) {
return type.cast(CONTAINER_CONTEXT.singletonObjectRegistry().getSingleton(type));
}

@SuppressWarnings("unchecked")
public <T> T get(TypeDescriptor typeDescriptor) {
return (T) CONTAINER_CONTEXT.singletonObjectRegistry().getSingleton(typeDescriptor);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,10 @@ private void handlePreDestroy(ContainerObj object) {
}

private void callPreDestroyProcessor(ContainerObj object) {
if (!object.isSingletonScope())
return;
if (!object.isSingletonScope()) return;

Object instance = context.singletonObjectRegistry().getSingleton(object.getType());
if (instance == null)
return;
Object instance = context.singletonObjectRegistry().getSingleton(object.getTypeDescriptor());
if (instance == null) return;

for (ContainerObjDestroyProcessor destroyProcessor : this.context.destroyProcessors()) {
destroyProcessor.processPreDestroy(object, instance);
Expand All @@ -69,16 +67,14 @@ private void handlePostDestroy(ContainerObj object) {

this.context.containerObjectBinder().unbind(type);
this.context.objectCollectorRegistry().removeFromCollectors(object);
this.context.singletonObjectRegistry().removeSingleton(type);
this.context.singletonObjectRegistry().removeSingleton(object.getTypeDescriptor());
}

private void callPostDestroyProcessor(ContainerObj object) {
if (!object.isSingletonScope())
return;
if (!object.isSingletonScope()) return;

Object instance = context.singletonObjectRegistry().getSingleton(object.getType());
if (instance == null)
return;
Object instance = context.singletonObjectRegistry().getSingleton(object.getTypeDescriptor());
if (instance == null) return;

for (ContainerObjDestroyProcessor destroyProcessor : this.context.destroyProcessors()) {
destroyProcessor.processPostDestroy(object, instance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import io.fairyproject.container.node.loader.collection.InstanceEntry;
import io.fairyproject.container.object.ContainerObj;
import io.fairyproject.container.object.LifeCycle;
import io.fairyproject.container.object.provider.ConstructorInstanceProvider;
import io.fairyproject.container.object.provider.InstanceProvider;
import io.fairyproject.container.object.provider.MethodInvokeInstanceProvider;
import io.fairyproject.container.object.resolver.ContainerObjectFactory;
import io.fairyproject.container.object.resolver.ContainerObjectResolver;
import io.fairyproject.container.object.singleton.SingletonObjectRegistry;
Expand All @@ -47,7 +49,6 @@
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
Expand All @@ -63,46 +64,48 @@ public class ContainerNodeLoader {
private ContainerObjectResolver containerObjectResolver;
private InstanceCollection collection;

@NotNull
private static Object createInstance(ContainerObj obj, Object[] dependencies, InstanceProvider instanceProvider) {
Object instance;
try {
instance = instanceProvider.provide(dependencies);
} catch (Exception ex) {
throw new IllegalStateException("Failed to provide instance for " + obj.getType().getName(), ex);
}

return instance;
}

public boolean load() {
this.containerObjectResolver = ContainerObjectResolver.create(
this.context.containerObjectBinder(),
new ContainerObjectFactory() {
@Override
public CompletableFuture<Object> createInstance(Class<?> type) throws Exception {
return findSingletonInstance(type);
}

@Override
public CompletableFuture<Object> createInstance(TypeDescriptor typeDescriptor) throws Exception {
return findSingletonInstance(typeDescriptor);
}
},
new ContainerObjectFactory() {
@Override
public CompletableFuture<Object> createInstance(Class<?> type) throws Exception {
return findPrototypeInstance(type);
}

@Override
public CompletableFuture<Object> createInstance(TypeDescriptor typeDescriptor) throws Exception {
return findPrototypeInstance(typeDescriptor);
}
}
);
this.containerObjectResolver = ContainerObjectResolver.create(this.context.containerObjectBinder(), new ContainerObjectFactory() {
@Override
public CompletableFuture<Object> createInstance(Class<?> type) throws Exception {
return findSingletonInstance(type);
}

@Override
public CompletableFuture<Object> createInstance(TypeDescriptor typeDescriptor) throws Exception {
return findSingletonInstance(typeDescriptor);
}
}, new ContainerObjectFactory() {
@Override
public CompletableFuture<Object> createInstance(Class<?> type) throws Exception {
return findPrototypeInstance(type);
}

@Override
public CompletableFuture<Object> createInstance(TypeDescriptor typeDescriptor) throws Exception {
return findPrototypeInstance(typeDescriptor);
}
});
this.collection = InstanceCollection.create();

BlockingThreadAwaitQueue queue = BlockingThreadAwaitQueue.create();

this.node.resolve();
if (!this.node.isResolved())
return false;
if (!this.node.isResolved()) return false;

CompletableFuture<?> completableFuture = this.provideInstances()
.thenRun(this::callNodePreInitProcessors)
.thenComposeAsync(directlyCompose(this::callPreInitProcessors), queue)
.thenRun(this::handleObjCollector)
.thenComposeAsync(directlyCompose(this::callPostInitProcessors), queue)
.thenRun(this::callNodePostInitProcessors);
CompletableFuture<?> completableFuture = this.provideInstances().thenRun(this::callNodePreInitProcessors).thenComposeAsync(directlyCompose(this::callPreInitProcessors), queue).thenRun(this::handleObjCollector).thenComposeAsync(directlyCompose(this::callPostInitProcessors), queue).thenRun(this::callNodePostInitProcessors);

queue.await(completableFuture::isDone);
ThrowingRunnable.sneaky(completableFuture::get).run();
Expand All @@ -124,16 +127,14 @@ private void callNodePostInitProcessors() {
private CompletableFuture<Object> findSingletonInstance(Class<?> type) {
SingletonObjectRegistry singletonObjectRegistry = this.context.singletonObjectRegistry();
Object instance = singletonObjectRegistry.getSingleton(type);
if (instance == null)
throw new IllegalStateException("Singleton instance for " + type.getName() + " is null!");
if (instance == null) throw new IllegalStateException("Singleton instance for " + type.getName() + " is null!");

return CompletableFuture.completedFuture(instance);
}

private CompletableFuture<Object> findPrototypeInstance(Class<?> type) {
ContainerObj obj = this.context.containerObjectBinder().getBinding(type);
if (obj == null)
throw new IllegalStateException("Container object for " + type.getName() + " is null!");
if (obj == null) throw new IllegalStateException("Container object for " + type.getName() + " is null!");

try {
return this.provideInstance(obj);
Expand All @@ -144,18 +145,15 @@ private CompletableFuture<Object> findPrototypeInstance(Class<?> type) {

private CompletableFuture<Object> findSingletonInstance(TypeDescriptor typeDescriptor) {
SingletonObjectRegistry singletonObjectRegistry = this.context.singletonObjectRegistry();
// 注意:当前 SingletonObjectRegistry 可能还没有支持 TypeDescriptor,这里先使用 rawType
Object instance = singletonObjectRegistry.getSingleton(typeDescriptor.getRawType());
if (instance == null)
throw new IllegalStateException("Singleton instance for " + typeDescriptor + " is null!");
Object instance = singletonObjectRegistry.getSingleton(typeDescriptor);
if (instance == null) throw new IllegalStateException("Singleton instance for " + typeDescriptor + " is null!");

return CompletableFuture.completedFuture(instance);
}

private CompletableFuture<Object> findPrototypeInstance(TypeDescriptor typeDescriptor) {
ContainerObj obj = this.context.containerObjectBinder().getBinding(typeDescriptor);
if (obj == null)
throw new IllegalStateException("Container object for " + typeDescriptor + " is null!");
if (obj == null) throw new IllegalStateException("Container object for " + typeDescriptor + " is null!");

try {
return this.provideInstance(obj);
Expand All @@ -174,24 +172,20 @@ private CompletableFuture<?> callPreInitProcessors() {
for (InstanceEntry entry : snapshot) {
Object instance = entry.getInstance();
ContainerObj object = entry.getContainerObject();
if (!this.trySetLifeCycle(object, LifeCycle.PRE_INIT))
continue;
if (!this.trySetLifeCycle(object, LifeCycle.PRE_INIT)) continue;

CompletableFuture<?> chain = null;
for (ContainerObjInitProcessor initProcessor : this.context.initProcessors()) {
try {
Supplier<CompletableFuture<?>> callback = () -> initProcessor.processPreInitialization(object, instance, this.containerObjectResolver);
if (chain == null)
chain = callback.get();
else
chain = chain.thenCompose($ -> callback.get());
if (chain == null) chain = callback.get();
else chain = chain.thenCompose($ -> callback.get());
} catch (Throwable throwable) {
ContainerLogger.report(this.node, object, throwable, "processing pre initialization");
}
}

if (chain != null)
futures.add(chain);
if (chain != null) futures.add(chain);
}

return AsyncUtils.allOf(futures);
Expand All @@ -203,33 +197,28 @@ private CompletableFuture<?> callPostInitProcessors() {
for (InstanceEntry entry : this.collection) {
Object instance = entry.getInstance();
ContainerObj object = entry.getContainerObject();
if (!this.trySetLifeCycle(object, LifeCycle.POST_INIT))
continue;
if (!this.trySetLifeCycle(object, LifeCycle.POST_INIT)) continue;

CompletableFuture<?> chain = null;
for (ContainerObjInitProcessor initProcessor : this.context.initProcessors()) {
try {
Supplier<CompletableFuture<?>> callback = () -> initProcessor.processPostInitialization(object, instance);
if (chain == null)
chain = callback.get();
else
chain = chain.thenCompose($ -> callback.get());
if (chain == null) chain = callback.get();
else chain = chain.thenCompose($ -> callback.get());
} catch (Throwable throwable) {
ContainerLogger.report(this.node, object, throwable, "processing post initialization");
}
}

if (chain != null)
futures.add(chain);
if (chain != null) futures.add(chain);
}

return AsyncUtils.allOf(futures);
}

private CompletableFuture<?> provideInstances() {
return this.node.forEachClockwiseAwait(obj -> {
if (obj.isPrototypeScope())
return AsyncUtils.empty();
if (obj.isPrototypeScope()) return AsyncUtils.empty();

try {
return this.provideInstance(obj);
Expand All @@ -249,8 +238,8 @@ private CompletableFuture<Object> provideInstance(ContainerObj obj) throws Excep
return AsyncUtils.empty();
}

if (singletonObjectRegistry.containsSingleton(objectType)) {
Object instance = singletonObjectRegistry.getSingleton(objectType);
if (singletonObjectRegistry.containsSingleton(obj.getTypeDescriptor())) {
Object instance = singletonObjectRegistry.getSingleton(obj.getTypeDescriptor());
this.postInstanceConstruct(instance, obj);

return AsyncUtils.empty();
Expand All @@ -262,36 +251,31 @@ private CompletableFuture<Object> provideInstance(ContainerObj obj) throws Excep
throw new IllegalStateException("Instance provider for " + objectType.getName() + " is null!");
}

CompletableFuture<Object[]> future = this.containerObjectResolver.resolveInstances(instanceProvider.getDependencies());
return future
.thenApplyAsync(objects -> createInstance(obj, objects, instanceProvider), obj.getThreadingMode().getExecutor())
.thenCompose(this::callConstructProcessors)
.thenApply(instance -> {
if (obj.isSingletonScope()) {
singletonObjectRegistry.registerSingleton(objectType, instance);
}

this.postInstanceConstruct(instance, obj);
return instance;
});
CompletableFuture<Object[]> future;
if (instanceProvider instanceof ConstructorInstanceProvider) {
ConstructorInstanceProvider constructorProvider = (ConstructorInstanceProvider) instanceProvider;
future = this.resolveInstancesByTypeDescriptors(constructorProvider.getParameterTypeDescriptors());
} else if (instanceProvider instanceof MethodInvokeInstanceProvider) {
MethodInvokeInstanceProvider methodProvider = (MethodInvokeInstanceProvider) instanceProvider;
future = this.resolveInstancesByTypeDescriptors(methodProvider.getParameterTypeDescriptors());
} else {
future = this.containerObjectResolver.resolveInstances(instanceProvider.getDependencies());
}

return future.thenApplyAsync(objects -> createInstance(obj, objects, instanceProvider), obj.getThreadingMode().getExecutor()).thenCompose(this::callConstructProcessors).thenApply(instance -> {
if (obj.isSingletonScope()) {
singletonObjectRegistry.registerSingleton(obj.getTypeDescriptor(), instance);
}

this.postInstanceConstruct(instance, obj);
return instance;
});
}

private void postInstanceConstruct(Object instance, ContainerObj obj) {
this.collection.add(instance, obj);
}

@NotNull
private static Object createInstance(ContainerObj obj, Object[] dependencies, InstanceProvider instanceProvider) {
Object instance;
try {
instance = instanceProvider.provide(dependencies);
} catch (Exception ex) {
throw new IllegalStateException("Failed to provide instance for " + obj.getType().getName(), ex);
}

return instance;
}

private CompletableFuture<Object> callConstructProcessors(Object instance) {
List<CompletableFuture<?>> futures = new ArrayList<>();

Expand All @@ -303,16 +287,14 @@ private CompletableFuture<Object> callConstructProcessors(Object instance) {
}

private boolean trySetLifeCycle(ContainerObj obj, LifeCycle lifeCycle) {
if (obj.getScope() != InjectableScope.SINGLETON)
return true;
if (obj.getScope() != InjectableScope.SINGLETON) return true;

Class<?> type = obj.getType();
TypeDescriptor typeDescriptor = obj.getTypeDescriptor();
SingletonObjectRegistry singletonObjectRegistry = this.context.singletonObjectRegistry();
LifeCycle current = singletonObjectRegistry.getSingletonLifeCycle(type);
if (current.isAfter(lifeCycle))
return false;
LifeCycle current = singletonObjectRegistry.getSingletonLifeCycle(typeDescriptor);
if (current.isAfter(lifeCycle)) return false;

singletonObjectRegistry.setSingletonLifeCycle(type, lifeCycle);
singletonObjectRegistry.setSingletonLifeCycle(typeDescriptor, lifeCycle);
return true;
}

Expand Down Expand Up @@ -341,4 +323,18 @@ private <T> T handleThrow(ContainerObj obj, Function<ContainerObj, T> function)
}
}

private CompletableFuture<Object[]> resolveInstancesByTypeDescriptors(TypeDescriptor[] typeDescriptors) throws Exception {
Object[] args = new Object[typeDescriptors.length];
CompletableFuture<?>[] futures = new CompletableFuture<?>[typeDescriptors.length];

for (int i = 0; i < args.length; i++) {
TypeDescriptor typeDescriptor = typeDescriptors[i];
int index = i;

futures[i] = this.containerObjectResolver.resolveInstance(typeDescriptor).thenAccept(instance -> args[index] = instance);
}

return CompletableFuture.allOf(futures).thenApply($ -> args);
}

}
Loading
Loading