
com.openthinks.libs.utilities.lookup.LookupPool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utilities Show documentation
Show all versions of utilities Show documentation
A common utilities for other projects under domain com.openthinks.
The newest version!
package com.openthinks.libs.utilities.lookup;
import java.util.Optional;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.openthinks.libs.utilities.Checker;
import com.openthinks.libs.utilities.InstanceUtilities;
import com.openthinks.libs.utilities.InstanceUtilities.InstanceWrapper;
import com.openthinks.libs.utilities.pools.object.ObjectPool;
/**
* ClassName: LookupPool
* Function: It is used for store shared object instances and find other SPI
* Reason: follow the design pattern of fly weight to reduce instantiate new
* object.
* Notice: avoid store or find those object which include its own state and will
* be changed;
* Usage:
*
*
*
* //get gloabl instance of LookupPool
* LookupPool lookupPool = LookupPools.gloabl();
*
* //get a named instance of LookupPool
* lookupPool = LookupPools.get("pool-1");
*
* // instance by class directly
* LookupInterfaceImpl instanceImpl1 = lookupPool.lookup(LookupInterfaceImpl.class);
*
* // instance by customized implementation class
* LookupInterface instanceImpl2 = lookupPool.lookup(LookupInterface.class,InstanceWrapper.build(LookupInterfaceImpl.class));
*
* // lookup shared object already existed
* LookupInterface instanceImpl3 = lookupPool.lookup(LookupInterface.class);
* assert instanceImpl2==instanceImpl3 ;
*
* // register a shared object by name
* lookupPool.register("beanName1",instanceImpl1);
* // lookup shared object by name
* LookupInterface instanceImpl4 = lookupPool.lookup("beanName1");
*
* assert instanceImpl1==instanceImpl4 ;
*
* // clear all shared objects and mappings
* lookupPool.cleanUp();
*
*
*
*
* date: Sep 8, 2017 3:15:29 PM
*
* @author [email protected]
* @version 1.0
* @since JDK 1.8
*/
public abstract class LookupPool {
protected final ObjectPool objectPool;
protected final ReadWriteLock lock;
public abstract String name();
LookupPool() {
objectPool = new ObjectPool();
lock = new ReentrantReadWriteLock();
}
/**
* lookup a object by its type, if not find firstly, try to instance by
* instanceType and constructor parameters args
*
* @param
* lookup object type
* @param type
* Class lookup key type
* @param args
* Object[] instance constructor parameters
* @return T lookup object or null
*/
public T lookup(Class type, Object... args) {
return lookup(type, null, args);
}
/**
* lookup a object by its type, if not find firstly, try to instance by
* instanceType and constructor parameters args
*
* @param
* lookup object type
* @param
* lookup object type
* @param searchType
* Class lookup key type
* @param instancewrapper
* Class instance type when not lookup the key
* @param args
* Object[] instance constructor parameters
* @return T lookup object or null
*/
public T lookup(final Class searchType, InstanceWrapper instancewrapper, Object... args) {
T object = null;
lock.readLock().lock();
try {
object = objectPool.get(searchType);
} finally {
lock.readLock().unlock();
}
if (object == null) {
lock.writeLock().lock();
try {
object = InstanceUtilities.create(searchType, instancewrapper, args);
register(searchType, object);
} finally {
lock.writeLock().unlock();
}
}
return object;
}
/**
* look up object by its bean name
*
* @param
* lookup object type
* @param beanName
* String lookup object mapping name
* @return T lookup object or null
*/
public T lookup(String beanName) {
lock.readLock().lock();
try {
return objectPool.get(beanName);
} finally {
lock.readLock().unlock();
}
}
/**
* lookup a optional object by its type, if not find firstly, try to instance by
* instanceType and constructor parameters args
*
* @param
* lookup object type
* @param type
* Class lookup key type
* @param args
* Object[] instance constructor parameters
* @return Optional of lookup object
*/
public Optional lookupIf(Class type, Object... args) {
return Optional.ofNullable(lookup(type, args));
}
/**
* lookup a optional object by its type, if not find firstly, try to instance by
* instanceType and constructor parameters args
*
* @param
* lookup object type
* @param
* lookup object type
* @param searchType
* Class lookup key type
* @param instancewrapper
* Class instance type when not lookup the key
* @param args
* Object[] instance constructor parameters
* @return Optional of lookup object
*/
public Optional lookupIf(final Class searchType, InstanceWrapper instancewrapper,
Object... args) {
return Optional.ofNullable(lookup(searchType, instancewrapper, args));
}
/**
* look up optional object by its bean name
*
* @param
* lookup object type
* @param beanName
* String lookup object mapping name
* @return Optional of lookup object
*/
public Optional lookupIf(String beanName) {
return Optional.ofNullable(lookup(beanName));
}
/**
*
* lookupSPI:this will used {@link ServiceLoader} to load SPI which defined in
* folder META-INF/services.
* It will first to try to load instance from cached {@link ObjectPool}, if not
* found, then try to load SPI class and instantiate it.
* Notice: only load and instantiate first SPI class in defined file
*
* @param
* lookup SPI interface class
* @param spiInterface
* SPI interface or abstract class type
* @param args
* constructor arguments
* @return implementation of parameter spiInterface
*/
public T lookupSPI(Class spiInterface, Object... args) {
return lookupFocusSPI(spiInterface, null, args);
}
/**
*
* lookupFocusSPI:this will used {@link ServiceLoader} to load SPI which defined
* in folder META-INF/services.
* It will first to try to load instance from cached {@link ObjectPool}, if not
* found, then try to load SPI class and instantiate it.
* Notice: only load and instantiate focused SPI class in defined file
*
* @param
* lookup SPI interface class
* @param spiInterface
* SPI interface or abstract class type
* @param focusClassName
* focused SPI implementation class aname
* @param args
* constructor arguments
* @return implementation of parameter spiInterface
*
*/
public T lookupFocusSPI(Class spiInterface, String focusClassName, Object... args) {
T object = null;
lock.readLock().lock();
try {
object = objectPool.get(spiInterface);
} finally {
lock.readLock().unlock();
}
if (object == null) {
lock.writeLock().lock();
try {
ServiceLoader serviceLoader = ServiceLoader.load(spiInterface, focusClassName, args);
object = serviceLoader.iterator().next();
Checker.require(object).notNull("Cannot found SPI implementation for " + spiInterface);
register(spiInterface, object);
} finally {
lock.writeLock().unlock();
}
}
return object;
}
/**
*
* register an instance, which key is object.getClass().
*
* @param
* registered object class type
* @param object
* instance which need registered
*/
public void register(T object) {
if (object != null) {
lock.writeLock().tryLock();
try {
objectPool.put(object.getClass(), object);
} finally {
lock.writeLock().unlock();
}
}
}
/**
* register an instance, which key is given parameter classType
*
* @param
* registered object class type
* @param classType
* Class as the key for registered instance
* @param object
* instance which need registered
*/
public void register(Class classType, T object) {
if (object != null) {
lock.writeLock().tryLock();
try {
objectPool.put(classType, object);
} finally {
lock.writeLock().unlock();
}
}
}
/**
* register object and mapping it to given bean name
*
* @param
* register object type
* @param beanName
* String bean name
* @param object
* register object
*/
public void register(String beanName, T object) {
if (object != null) {
lock.writeLock().lock();
try {
objectPool.put(beanName, object);
} finally {
lock.writeLock().unlock();
}
}
}
void cleanUp() {
lock.writeLock().lock();
try {
objectPool.cleanUp();
} finally {
lock.writeLock().unlock();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy