public final class ProxyFactory
extends java.lang.Object
ProxyAssembler
. Please see the description of that class for the
rationale of this mechanism as an alternative to Java's standard, dynamic
proxy implementation.
The access points to this factory's functionality are the public, static
variants of the getProxy
method, which allow the definition
of a new proxy class, based on a given superclass, list of interfaces to
implement, and an invocation handler to which method invocations are
dispatched. Several additional options are available to tailor the proxy
class to specific needs. Please see:
Modifier and Type | Class and Description |
---|---|
private static class |
ProxyFactory.CacheKey
A cache key which takes into account a proxy class' parent, implemented
interfaces, whether only declared methods are implemented, and list of
methods to be omitted from the proxy.
|
Modifier and Type | Field and Description |
---|---|
private java.util.Map<ProxyFactory.CacheKey,java.lang.ref.WeakReference<java.lang.Class<?>>> |
cache
Cache of proxy classes which already have been assembled
|
private AsmClassLoader |
loader
Custom class loader to load proxy classes
|
private int |
nextSuffix
Suffix to ensure unique proxy class names
|
private static ProxyFactory |
singleton
Singleton instance of this factory class
|
Modifier | Constructor and Description |
---|---|
private |
ProxyFactory()
Private constructor to ensure singleton instance.
|
Modifier and Type | Method and Description |
---|---|
private java.lang.reflect.Method[] |
gatherMethods(java.lang.Class<?>[] interfaces,
boolean declaredOnly,
java.lang.reflect.Method[] doNotProxy)
Gather the final list of methods to be implemented explicitly by the
dynamic proxy class.
|
static <T> T |
getProxy(java.lang.Class<?> parent,
java.lang.Class<?>[] interfaces,
boolean declaredOnly,
java.lang.reflect.Method[] doNotProxy,
ProxyAssemblerPlugin plugin,
java.lang.reflect.InvocationHandler handler)
Get an instance of a proxy class which subclasses the given parent class
and implements the specified interfaces.
|
static <T> T |
getProxy(java.lang.Class<?> parent,
java.lang.Class<?>[] interfaces,
java.lang.reflect.InvocationHandler handler)
Get an instance of a proxy class which subclasses the given parent class
and implements the specified interfaces.
|
static <T> T |
getProxy(java.lang.Class<? extends java.lang.reflect.InvocationHandler> parent,
java.lang.Class<?>[] interfaces)
Get an instance of a proxy class which subclasses the given parent class
and implements the specified interfaces.
|
static <T> T |
getProxy(java.lang.Class<? extends java.lang.reflect.InvocationHandler> parent,
java.lang.Class<?>[] interfaces,
boolean declaredOnly,
java.lang.reflect.Method[] doNotProxy)
Get an instance of a proxy class which subclasses the given parent class
and implements the specified interfaces.
|
private <T> T |
getProxyImpl(java.lang.Class<?> parent,
java.lang.Class<?>[] interfaces,
boolean declaredOnly,
java.lang.reflect.Method[] doNotProxy,
ProxyAssemblerPlugin plugin,
java.lang.reflect.InvocationHandler handler)
Get an instance of a proxy class which subclasses the given parent class
and implements the specified interfaces.
|
private java.lang.reflect.Method |
identifyBestMethod(java.util.Set<java.lang.reflect.Method> methods)
Given a set of methods, identify the best method to implement in the
dynamic proxy.
|
static boolean |
isProxyClass(java.lang.Class<?> clazz)
Indicate whether the given class represents a proxy class generated by
this factory.
|
private java.lang.String |
makeProxyClassName(java.lang.Class<?> parent,
java.lang.String parentName)
Given the proxy's superclass and its name, generate a unique name of the
proxy class, which can be used to load the class in the custom, proxy
class loader.
|
private static final ProxyFactory singleton
private final java.util.Map<ProxyFactory.CacheKey,java.lang.ref.WeakReference<java.lang.Class<?>>> cache
private final AsmClassLoader loader
private int nextSuffix
private ProxyFactory()
public static <T> T getProxy(java.lang.Class<?> parent, java.lang.Class<?>[] interfaces, java.lang.reflect.InvocationHandler handler)
If a proxy class does not yet exist which meets the given criteria, one is assembled and loaded on the fly.
Implementation Note: if multiple interfaces specify methods with the same names, compatible signatures and return types, but different lists of exception types, the first method discovered which has a return type assignable from all other, matching methods is used for the dynamic proxy, regardless of the exception list. Therefore, callers should take care to specify methods with matching exception lists, if methods with the same name, signature, and compatible return types are specified across interfaces.
T
- Type of the proxy class which will be returned.parent
- Superclass of the proxy class.interfaces
- Array of interfaces which must be implemented by the proxy
class.handler
- Handler to which to dispatch method invocations.parent
and which implements the
methods defined by interfaces
.java.lang.IllegalArgumentException
- if multiple interfaces specify methods which share a name and
parameter signature, but which have incompatible return types.public static <T> T getProxy(java.lang.Class<?> parent, java.lang.Class<?>[] interfaces, boolean declaredOnly, java.lang.reflect.Method[] doNotProxy, ProxyAssemblerPlugin plugin, java.lang.reflect.InvocationHandler handler)
If a proxy class does not yet exist which meets the given criteria, one is assembled and loaded on the fly.
Implementation Note: if multiple interfaces specify methods with compatible signatures and return types, but different lists of exception types, the first method discovered which has a return type which is assignable from all other, matching methods is used for the dynamic proxy, regardless of the exception list. The order in which methods are checked is indeterminate. Therefore, callers should be careful to specify methods with matching exception lists, if methods with the same name, signature, and compatible return types are specified across interfaces.
T
- Type of the proxy class which will be returned.parent
- Superclass of the proxy class.interfaces
- Array of interfaces which must be implemented by the proxy
class.declaredOnly
- If true
, only methods explicitly declared by the
given interfaces are used; if false
, methods
declared by the given interfaces and by any of their ancestor
interfaces are used.doNotProxy
- An optional array of Method
objects which are not
to be implemented by the dynamically generated proxy. This
option should be used only to represent methods which already
are implemented by the proxy class' superclass.handler
- Handler to which to dispatch method invocations. This value
must not be null
.parent
and which implements the
methods defined by interfaces
.java.lang.IllegalArgumentException
- if handler
is null
;
if multiple interfaces specify methods which share a name and
parameter signature, but which have incompatible return types.public static <T> T getProxy(java.lang.Class<? extends java.lang.reflect.InvocationHandler> parent, java.lang.Class<?>[] interfaces)
InvocationHandler
instance. It should be used
when the parent class is expected to fulfill the role of invocation
handler.
If a proxy class does not yet exist which meets the given criteria, one is assembled and loaded on the fly.
Implementation Note: if multiple interfaces specify methods with compatible signatures and return types, but different lists of exception types, the first method discovered which has a return type which is assignable from all other, matching methods is used for the dynamic proxy, regardless of the exception list. The order in which methods are checked is indeterminate. Therefore, callers should be careful to specify methods with matching exception lists, if methods with the same name, signature, and compatible return types are specified across interfaces.
T
- Type of the proxy class which will be returned.parent
- Superclass of the proxy class, which must implement the
InvocationHandler
interface.interfaces
- Array of interfaces which must be implemented by the proxy
class.parent
and which implements the
methods defined by interfaces
.java.lang.IllegalArgumentException
- if multiple interfaces specify methods which share a name and
parameter signature, but which have incompatible return types.public static <T> T getProxy(java.lang.Class<? extends java.lang.reflect.InvocationHandler> parent, java.lang.Class<?>[] interfaces, boolean declaredOnly, java.lang.reflect.Method[] doNotProxy)
InvocationHandler
instance. It should be used
when the parent class is expected to fulfill the role of invocation
handler.
If a proxy class does not yet exist which meets the given criteria, one is assembled and loaded on the fly.
Implementation Note: if multiple interfaces specify methods with compatible signatures and return types, but different lists of exception types, the first method discovered which has a return type which is assignable from all other, matching methods is used for the dynamic proxy, regardless of the exception list. The order in which methods are checked is indeterminate. Therefore, callers should be careful to specify methods with matching exception lists, if methods with the same name, signature, and compatible return types are specified across interfaces.
T
- Type of the proxy class which will be returned.parent
- Superclass of the proxy class, which must implement the
InvocationHandler
interface.interfaces
- Array of interfaces which must be implemented by the proxy
class.declaredOnly
- If true
, only methods explicitly declared by the
given interfaces are used; if false
, methods
declared by the given interfaces and by any of their ancestor
interfaces are used.doNotProxy
- An optional array of Method
objects which are not
to be implemented by the dynamically generated proxy. This
option should be used only to represent methods which already
are implemented by the proxy class' superclass.parent
and which implements the
methods defined by interfaces
.java.lang.IllegalArgumentException
- if multiple interfaces specify methods which share a name and
parameter signature, but which have incompatible return types.public static boolean isProxyClass(java.lang.Class<?> clazz)
clazz
- The class to be tested.true
if the given class represents a proxy class
generated by this factory, else false
.private <T> T getProxyImpl(java.lang.Class<?> parent, java.lang.Class<?>[] interfaces, boolean declaredOnly, java.lang.reflect.Method[] doNotProxy, ProxyAssemblerPlugin plugin, java.lang.reflect.InvocationHandler handler)
If a proxy class does not yet exist which meets the given criteria, one is assembled and loaded on the fly.
Implementation Note: if multiple interfaces specify methods with compatible signatures and return types, but different lists of exception types, the first method discovered which has a return type which is assignable from all other, matching methods is used for the dynamic proxy, regardless of the exception list. The order in which methods are checked is indeterminate. Therefore, callers should be careful to specify methods with matching exception lists, if methods with the same name, signature, and compatible return types are specified across interfaces.
T
- Type of the proxy class which will be returned.parent
- Superclass of the proxy class. If handler
is
null
, this class is expected to implement the
InvocationHandler
interface.interfaces
- Array of interfaces which must be implemented by the proxy
class.declaredOnly
- If true
, only methods explicitly declared by the
given interfaces are used; if false
, methods
declared by the given interfaces and by any of their ancestor
interfaces are used.doNotProxy
- An optional array of Method
objects which are not
to be implemented by the dynamically generated proxy. This
option should be used only to represent methods which already
are implemented by the proxy class' superclass.plugin
- An optional plugin which can override the assembly of arbitrary methods.handler
- Handler to which to dispatch method invocations. If
null
, the dynamic proxy instance itself will be
used as the invocation handler.parent
and which implements the
methods defined by interfaces
.java.lang.IllegalArgumentException
- if multiple interfaces specify methods which share a name and
parameter signature, but which have incompatible return types;
if parent
is an interface;
if any of the specified interfaces
are not
actually interfaces.private java.lang.String makeProxyClassName(java.lang.Class<?> parent, java.lang.String parentName)
.
) character as its
separator, whereas the internal name uses the forward slash
(/
).
The package of the superclass becomes the package of the proxy class.
The simple name of the proxy class is $__ProxyN
,
where N is an integer unique across all proxy classes generated
by this factory.
parent
- Parent class of proxy.parentName
- Fully qualified name of parent class.com.goldencode.proxy
package name.private java.lang.reflect.Method[] gatherMethods(java.lang.Class<?>[] interfaces, boolean declaredOnly, java.lang.reflect.Method[] doNotProxy)
interfaces
- Array of interfaces which must be implemented by the proxy
class.declaredOnly
- If true
, only methods explicitly declared by the
given interfaces are used; if false
, methods
declared by the given interfaces and by any of their ancestor
interfaces are used.doNotProxy
- An optional array of Method
objects which are not
to be implemented by the dynamically generated proxy. This
option should be used only to represent methods which already
are implemented by the proxy class' superclass.java.lang.IllegalArgumentException
- if multiple interfaces specify methods which share a name and
parameter signature, but which have incompatible return types.private java.lang.reflect.Method identifyBestMethod(java.util.Set<java.lang.reflect.Method> methods)
methods
- A set of methods which share a name and parameter signature,
but not necessarily the same return type.java.lang.IllegalArgumentException
- if multiple methods exist in the set, but none has a return
type that is assignable from all the others.