com.github.nill14.utils.init.impl.LazyPojo Maven / Gradle / Ivy
package com.github.nill14.utils.init.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.inject.Provider;
import com.github.nill14.utils.init.api.ILazyPojo;
import com.github.nill14.utils.init.api.IPojoFactory;
import com.github.nill14.utils.init.api.IPojoInitializer;
import com.github.nill14.utils.init.api.IPropertyResolver;
import com.github.nill14.utils.init.inject.ReflectionUtils;
import com.google.common.reflect.TypeToken;
@SuppressWarnings("serial")
public final class LazyPojo implements ILazyPojo, Provider {
public static ILazyPojo forSingleton(T singleton) {
return forSingleton(singleton, IPropertyResolver.empty());
}
public static ILazyPojo forSingleton(T singleton, IPropertyResolver resolver) {
IPojoFactory pojoFactory = PojoProviderFactory.singleton(singleton, resolver);
return new LazyPojo(pojoFactory, IPojoInitializer.empty());
}
public static ILazyPojo forBean(Class beanClass) {
return forBean(beanClass, IPropertyResolver.empty(), IPojoInitializer.empty());
}
public static ILazyPojo forBean(Class beanClass, IPropertyResolver resolver, IPojoInitializer initializer) {
IPojoFactory factory = new PojoInjectionFactory<>(TypeToken.of(beanClass), resolver);
return new LazyPojo<>(factory, initializer);
}
public static > ILazyPojo forProvider(Class providerClass) {
return forProvider(providerClass, IPropertyResolver.empty(), IPojoInitializer.empty());
}
public static > ILazyPojo forProvider(
Class providerClass, IPropertyResolver resolver, IPojoInitializer factoryInitializer) {
TypeToken typeToken = ReflectionUtils.getProviderReturnTypeToken(providerClass);
IPojoFactory pojoFactory = new PojoInjectionFactory<>(TypeToken.of(providerClass), resolver);
PojoFactoryAdapter factoryAdapter = new PojoFactoryAdapter(pojoFactory, typeToken, factoryInitializer);
return new LazyPojo<>(factoryAdapter, factoryAdapter);
}
public static ILazyPojo forProvider(
Provider provider, IPropertyResolver resolver, IPojoInitializer initializer) {
IPojoFactory pojoFactory = new PojoProviderFactory<>(provider, resolver);
return new LazyPojo<>(pojoFactory, initializer);
}
public static ILazyPojo forFactory(
IPojoFactory pojoFactory, IPojoInitializer initializer) {
return new LazyPojo<>(pojoFactory, initializer);
}
private final IPojoFactory factory;
private final IPojoInitializer initializer;
private volatile transient T instance;
public LazyPojo(IPojoFactory factory, IPojoInitializer initializer) {
this.factory = factory;
this.initializer = initializer;
}
@Override
public TypeToken getType() {
return factory.getType();
}
@Override
public T get() {
return getInstance();
}
@Override
public T getInstance() {
T instance = this.instance;
if (instance == null) {
synchronized (this) {
instance = this.instance;
if (instance == null) {
instance = factory.newInstance();
initializer.init(this, factory, instance);
this.instance = instance;
}
}
}
return instance;
}
@Override
public boolean freeInstance() {
boolean released = false;
T instance = this.instance;
if (instance != null) {
synchronized (this) {
instance = this.instance;
if (instance != null) {
this.instance = null;
initializer.destroy(this, factory, instance);
released = true;
}
}
}
return released;
}
@Override
public Future init(ExecutorService executor) {
return executor.submit(new Callable() {
@Override
public T call() throws Exception {
return getInstance();
}
});
}
@Override
public Future destroy(ExecutorService executor) {
return executor.submit(new Callable() {
@Override
public Boolean call() throws Exception {
return freeInstance();
}
});
}
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
synchronized (this) {
if (instance instanceof Serializable) {
stream.writeObject(instance);
} else {
stream.writeObject(null);
}
}
}
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
Object obj = stream.readObject();
synchronized (this) {
if (obj != null) {
this.instance = (T) obj;
}
}
}
@Override
public String toString() {
return String.format("%s(%s)@%s",
getClass().getSimpleName(),
factory.getType().toString(),
Integer.toHexString(System.identityHashCode(this)));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy