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.IBeanDescriptor;
import com.github.nill14.utils.init.api.ILazyPojo;
import com.github.nill14.utils.init.api.IPojoInitializer;
import com.github.nill14.utils.init.api.IPropertyResolver;
import com.github.nill14.utils.init.inject.PojoInjectionDescriptor;
@SuppressWarnings("serial")
public class LazyPojo implements ILazyPojo, Provider {
@SuppressWarnings("unchecked")
public static ILazyPojo forSingleton(T singleton) {
IBeanDescriptor pd = new PojoInjectionDescriptor<>((Class) singleton.getClass());
return new LazyPojo(() -> singleton, pd, IPojoInitializer.empty());
}
public static ILazyPojo forClass(Class beanClass) {
return forClass(beanClass, IPropertyResolver.empty(), IPojoInitializer.empty());
}
public static > ILazyPojo forFactory(Class beanClass, Class factoryClass) {
return forFactory(beanClass, factoryClass, IPropertyResolver.empty(), IPojoInitializer.empty());
}
public static ILazyPojo forClass(Class beanClass, IPropertyResolver resolver, IPojoInitializer super T> initializer) {
IBeanDescriptor pd = new PojoInjectionDescriptor<>(beanClass);
Provider factory = new PojoFactory<>(pd, resolver);
return new LazyPojo<>(factory, pd, initializer);
}
public static > ILazyPojo forFactory(Class beanClass,
Class factoryClass, IPropertyResolver resolver, IPojoInitializer super F> factoryInitializer) {
IBeanDescriptor pd = new PojoInjectionDescriptor<>(beanClass);
IBeanDescriptor pdFactory = new PojoInjectionDescriptor<>(factoryClass);
FactoryAdapter factoryAdapter = new FactoryAdapter(beanClass, pdFactory, factoryInitializer);
return new LazyPojo<>(factoryAdapter, pd, factoryAdapter);
}
private final Provider factory;
private final IBeanDescriptor pojoType;
private final IPojoInitializer super T> initializer;
private volatile transient T instance;
public LazyPojo(Provider factory, IBeanDescriptor pojoType, IPojoInitializer super T> initializer) {
this.factory = factory;
this.pojoType = pojoType;
this.initializer = initializer;
}
@Override
public Class extends T> getInstanceType() {
return pojoType.getRawType();
}
@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.get();
initializer.init(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(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);
}
}
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
Object obj = stream.readObject();
synchronized (this) {
if (obj != null) {
this.instance = getInstanceType().cast(obj);
}
}
}
@Override
public String toString() {
return String.format("%s(%s)@%s",
getClass().getSimpleName(),
pojoType.toString(),
Integer.toHexString(System.identityHashCode(this)));
}
public static class FactoryAdapter> implements Provider, IPojoInitializer {
private final ILazyPojo lazyFactory;
public FactoryAdapter(Class beanClass, IBeanDescriptor factoryType, IPojoInitializer super F> factoryInitializer) {
Provider factoryFactory = new PojoFactory<>(factoryType, IPropertyResolver.empty());
this.lazyFactory = new LazyPojo<>(factoryFactory, factoryType, factoryInitializer);
}
@Override
public T get() {
return lazyFactory.getInstance().get();
}
@Override
public void init(Provider> factory, T instance) {
//nothing to do, we want to initialize pojoFactory, not the instance created by the factory
//factoryInitializer was invoked by lazyFactory.getInstance() call
}
@Override
public void destroy(Provider> factory, T instance) {
//delegate the destruction to the factoryInitializer
//the factory is not re-used but re-created for each object
lazyFactory.freeInstance();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy