|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.jpu.patterns.singleton.onePerContext.OnePerContextManager
This class and its associated interfaces implement
a pattern that is a variant of Singleton intended for situations where you
need one instance of the class per "context", rather than one per classloader as is the
case with traditional singletons. A context can be any object of your choice, but can
optionally implement IContext
if if it wishes to be notified when objects are
created on its behalf.
To use it, have your class provide an accessible no-arg constructor, and declare a private static field like this:
private static OnePerContextManager _opcMgr = new OnePerContextManager(C.class);
where C is the name of your class. When you want an instance of it, call
(C)_opcMgr.getInstance(ctx);
where ctx
is the context. Typically you would wrap the above call in a public static
method of C like this:
public static C getInstance(Object ctx) {
return (C)_opcMgr.getInstance(ctx);
}
The class may then be treated much like a singleton, except that one instance will be
maintained per context, instead of one per classloader. Note ctx
can be null
, in which case it defaults to C.class
,
which provides traditional singleton behavior with one instance per classloader.
Custom Instantiation
By default the no-arg constructor of the class passed to the constructor is used to generate
the One-Per-Context instances. However you can change this behavior in either of two ways: 1) have the
context implement IContext
and define a IContext.newInstance(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager)
method that
instantiates the One-Per-Context and returns it; or 2) write your own IOnePerContextManager.IInstantiator
and
set it via IOnePerContextManager.setInstantiator(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager.IInstantiator)
. Method (1) takes precedence, so if
IContext.newInstance(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager)
returns non-null, its return value will be used as the One-Per-Context
instance and the instantiator will not be called.
Method (2) is generally intended for use by the One-Per-Context class itself to control its own instantiation, while Method (1) is intended for use by clients of the One-Per-Context class who need to substitute their own subclass implementation for use in particular contexts.
Custom Initialization
If you want each One-Per-Context instance to be notified of its associated
context, you can have it implement IOnePerContext
and implement the
IOnePerContext.initOnePerContext(java.lang.Object)
method. The method will be called
on newly-created One-Per-Context's.
You can also perform custom initialization of One-Per-Context's by writing your own
IOnePerContextManager.IInitializer
and adding it via IOnePerContextManager.addInitializer(int, org.jpu.patterns.singleton.onePerContext.IOnePerContextManager.IInitializer)
. You can
register as many initializers as you want, and they will be called in order on each newly
created One-Per-Context instance. This sort of initialization is performed immediately
after that described in the previous paragraph.
A third type of custom initialization can be performed by the context. To have the context
be notified when a new One-Per-Context is created on its behalf,
have it implement IContext
and override IContext.initialize(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager, java.lang.Object)
. This
method will be called immediately after that described in the previous paragraph.
Thread local Contexts
To avoid the necessity of passing around context references, you might want
to hold the context as a ThreadLocal
and adjust its value when
you want to change contexts. The code might look something like this:
public class Foo {
public static final Object DEFAULT_CTX = new Object();
public static Foo getInstance() {
return (Foo)_opcMgr.getInstance( _ctx.get() );
}
public static void setCtx(Object ctx) {
_ctx.set(ctx);
}
private static ThreadLocal _ctx = new ThreadLocal() {
protected Object initialValue() { return DEFAULT_CTX; }
};
private static OnePerContextManager _opcMgr = new OnePerContextManager(Foo.class);
}
For the full example see the source code of Foo
(source is included in the Javadoc's).
Context References
The One-Per-Context facility supports both weak and strong holding of
context references. Strong referencing can be requested by passing true
as the second parameter to OnePerContextManager(Class,boolean)
. If weak referencing
is requested (which is the default if the second parameter is omitted), the
facility's internal data structures will not prevent garbage collection of the context. When
the context is garbage collected, all One-Per-Context's associated with it
become inaccessible through this facility (though of course the application may yet
retain other references to them).
Nested Class Summary | |
static class |
OnePerContextManager.DefaultInstantiator
Default implementation of IOnePerContextManager.IInstantiator . |
Nested classes inherited from class org.jpu.patterns.singleton.onePerContext.IOnePerContextManager |
IOnePerContextManager.IInitializer, IOnePerContextManager.IInstantiator |
Field Summary |
Fields inherited from interface org.jpu.patterns.singleton.onePerContext.IOnePerContextManager |
DEFAULT_CONTEXT |
Constructor Summary | |
OnePerContextManager(java.lang.Class onePerContextClass)
Alias for " OnePerContextManager(onePerContextClass, false) ". |
|
OnePerContextManager(java.lang.Class onePerContextClass,
boolean strong)
Constructor. |
Method Summary | |
void |
addInitializer(int i,
IOnePerContextManager.IInitializer initializer)
Adds the given initializer at position " i ". |
static java.util.List |
findManagersByClass(java.lang.Class opcClass)
|
static java.util.List |
findManagersByClass(java.lang.Class opcClass,
boolean exact)
|
protected java.lang.Object |
getDefaultContext()
|
java.util.List |
getInitializers()
Returns a shallow copy of the internal list of IOnePerContextManager.IInitializer 's. |
java.lang.Object |
getInstance(java.lang.Object ctx)
Returns the One-Per-Context of the given class associated with the given context. |
IOnePerContextManager.IInstantiator |
getInstantiator()
Returns the IOnePerContextManager.IInstantiator used for instantiating One-Per-Context's. |
static java.util.Set |
getManagers()
Returns the set of all currently active OnePerContextManager 's. |
java.util.Map |
getObjects()
Returns a shallow copy of the internal map that maps contexts to One-Per-Context instances. |
java.lang.Class |
getOnePerContextClass()
Returns the class passed as the first parameter to the constructor. |
IOnePerContextManager.IInitializer |
removeInitializer(int i)
Removes the given initializer at position " i ". |
boolean |
removeInitializer(IOnePerContextManager.IInitializer ini)
Removes the given initializer. |
void |
setInstantiator(IOnePerContextManager.IInstantiator i)
Sets the IOnePerContextManager.IInstantiator to be used for instantiating One-Per-Context's. |
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
public OnePerContextManager(java.lang.Class onePerContextClass)
OnePerContextManager(onePerContextClass, false)
".
public OnePerContextManager(java.lang.Class onePerContextClass, boolean strong)
onePerContextClass
- The class of One-Per-Context's that will be created by subsequent calls to
getInstance(Object)
.strong
- Indicates whether references to newly-created instances should
be held strongly or weakly. If the context defines equals()
and hashCode()
in terms of
object identity, this should usually be false
; else it should be true
. For instance if the
context is a String
or a primitive type, strong
should be true
.Method Detail |
public static java.util.List findManagersByClass(java.lang.Class opcClass)
public static java.util.List findManagersByClass(java.lang.Class opcClass, boolean exact)
public static java.util.Set getManagers()
OnePerContextManager
's. The returned
set is a shallow copy of the internal data structure, so the caller can modify it at will.
public java.lang.Class getOnePerContextClass()
IOnePerContextManager
getOnePerContextClass
in interface IOnePerContextManager
public java.util.Map getObjects()
IOnePerContextManager
Map
is a copy, the caller can query and modify it at will without synchronization.
getObjects
in interface IOnePerContextManager
public java.util.List getInitializers()
IOnePerContextManager
IOnePerContextManager.IInitializer
's. Since
the List
is a copy, the caller can query and modify it at will without synchronization.
getInitializers
in interface IOnePerContextManager
public void addInitializer(int i, IOnePerContextManager.IInitializer initializer)
IOnePerContextManager
i
".
addInitializer
in interface IOnePerContextManager
public IOnePerContextManager.IInitializer removeInitializer(int i)
IOnePerContextManager
i
".
removeInitializer
in interface IOnePerContextManager
public boolean removeInitializer(IOnePerContextManager.IInitializer ini)
IOnePerContextManager
removeInitializer
in interface IOnePerContextManager
public IOnePerContextManager.IInstantiator getInstantiator()
IOnePerContextManager
IOnePerContextManager.IInstantiator
used for instantiating One-Per-Context's.
getInstantiator
in interface IOnePerContextManager
public void setInstantiator(IOnePerContextManager.IInstantiator i)
IOnePerContextManager
IOnePerContextManager.IInstantiator
to be used for instantiating One-Per-Context's.
setInstantiator
in interface IOnePerContextManager
protected java.lang.Object getDefaultContext()
public java.lang.Object getInstance(java.lang.Object ctx)
IOnePerContextManager
getInstance
in interface IOnePerContextManager
ctx
- The context. Can be null
in which case onePerContextClass
is used as the context.
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |