org.logicalcobwebs.cglib.proxy
Class Enhancer

java.lang.Object
  extended by org.logicalcobwebs.cglib.core.AbstractClassGenerator
      extended by org.logicalcobwebs.cglib.proxy.Enhancer
All Implemented Interfaces:
ClassGenerator

public class Enhancer
extends AbstractClassGenerator

Generates dynamic subclasses to enable method interception. This class started as a substitute for the standard Dynamic Proxy support included with JDK 1.3, but one that allowed the proxies to extend a concrete base class, in addition to implementing interfaces. The dynamically generated subclasses override the non-final methods of the superclass and have hooks which callback to user-defined interceptor implementations.

The original and most general callback type is the MethodInterceptor, which in AOP terms enables "around advice"--that is, you can invoke custom code both before and after the invocation of the "super" method. In addition you can modify the arguments before calling the super method, or not call it at all.

Although MethodInterceptor is generic enough to meet any interception need, it is often overkill. For simplicity and performance, additional specialized callback types, such as LazyLoader are also available. Often a single callback will be used per enhanced class, but you can control which callback is used on a per-method basis with a CallbackFilter.

The most common uses of this class are embodied in the static helper methods. For advanced needs, such as customizing the ClassLoader to use, you should create a new instance of Enhancer. Other classes within CGLIB follow a similar pattern.

All enhanced objects implement the Factory interface, unless setUseFactory(boolean) is used to explicitly disable this feature. The Factory interface provides an API to change the callbacks of an existing object, as well as a faster and easier way to create new instances of the same type.

For an almost drop-in replacement for java.lang.reflect.Proxy, see the Proxy class.


Nested Class Summary
(package private) static interface Enhancer.EnhancerKey
           
 
Nested classes/interfaces inherited from class org.logicalcobwebs.cglib.core.AbstractClassGenerator
AbstractClassGenerator.Source
 
Field Summary
private  java.lang.Object[] arguments
           
private  java.lang.Class[] argumentTypes
           
private  Callback[] callbacks
           
private  java.lang.Class[] callbackTypes
           
private  boolean classOnly
           
private  CallbackFilter filter
           
private  java.lang.Class[] interfaces
           
private static Enhancer.EnhancerKey KEY_FACTORY
           
private static AbstractClassGenerator.Source SOURCE
           
private  java.lang.Class superclass
           
private  boolean useFactory
           
 
Constructor Summary
Enhancer()
          Create a new Enhancer.
 
Method Summary
 java.lang.Object create()
          Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance.
 java.lang.Object create(java.lang.Class[] argumentTypes, java.lang.Object[] arguments)
          Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance.
static java.lang.Object create(java.lang.Class type, Callback callback)
          Helper method to create an intercepted object.
static java.lang.Object create(java.lang.Class superclass, java.lang.Class[] interfaces, Callback callback)
          Helper method to create an intercepted object.
static java.lang.Object create(java.lang.Class superclass, java.lang.Class[] interfaces, CallbackFilter filter, Callback[] callbacks)
          Helper method to create an intercepted object.
 java.lang.Class createClass()
          Generate a new class if necessary and return it without creating a new instance.
private  java.lang.Object createHelper()
           
private  java.lang.Object createUsingReflection(java.lang.Class type)
           
protected  java.lang.Object firstInstance(java.lang.Class type)
           
 void generateClass(ClassVisitor v)
           
protected  java.lang.ClassLoader getDefaultClassLoader()
           
protected  java.lang.Object nextInstance(java.lang.Object instance)
           
 void setCallback(Callback callback)
          Set the single Callback to use.
 void setCallbackFilter(CallbackFilter filter)
          Set the CallbackFilter used to map the generated class' methods to a particular callback index.
 void setCallbacks(Callback[] callbacks)
          Set the array of callbacks to use.
 void setCallbackType(java.lang.Class callbackType)
          Set the single type of Callback to use.
 void setCallbackTypes(java.lang.Class[] callbackTypes)
          Set the array of callback types to use.
 void setInterfaces(java.lang.Class[] interfaces)
          Set the interfaces to implement.
 void setSuperclass(java.lang.Class superclass)
          Set the class which the generated class will extend.
 void setUseFactory(boolean useFactory)
          Set whether the enhanced object instances should implement the Factory interface.
 
Methods inherited from class org.logicalcobwebs.cglib.core.AbstractClassGenerator
create, getClassLoader, getClassName, setClassLoader, setNamePrefix, setNamingPolicy, setStrategy, setUseCache
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

SOURCE

private static final AbstractClassGenerator.Source SOURCE

KEY_FACTORY

private static final Enhancer.EnhancerKey KEY_FACTORY

interfaces

private java.lang.Class[] interfaces

filter

private CallbackFilter filter

callbacks

private Callback[] callbacks

callbackTypes

private java.lang.Class[] callbackTypes

classOnly

private boolean classOnly

superclass

private java.lang.Class superclass

argumentTypes

private java.lang.Class[] argumentTypes

arguments

private java.lang.Object[] arguments

useFactory

private boolean useFactory
Constructor Detail

Enhancer

public Enhancer()
Create a new Enhancer. A new Enhancer object should be used for each generated object, and should not be shared across threads. To create additional instances of a generated class, use the Factory interface.

See Also:
Factory
Method Detail

setSuperclass

public void setSuperclass(java.lang.Class superclass)
Set the class which the generated class will extend. As a convenience, if the supplied superclass is actually an interface, setInterfaces will be called with the appropriate argument instead. A non-interface argument must not be declared as final, and must have an accessible constructor.

Parameters:
superclass - class to extend or interface to implement
See Also:
setInterfaces(Class[])

setInterfaces

public void setInterfaces(java.lang.Class[] interfaces)
Set the interfaces to implement. The Factory interface will always be implemented regardless of what is specified here.

Parameters:
interfaces - array of interfaces to implement, or null
See Also:
Factory

setCallbackFilter

public void setCallbackFilter(CallbackFilter filter)
Set the CallbackFilter used to map the generated class' methods to a particular callback index. New object instances will always use the same mapping, but may use different actual callback objects.

Parameters:
filter - the callback filter to use when generating a new class
See Also:
setCallbacks(org.logicalcobwebs.cglib.proxy.Callback[])

setCallback

public void setCallback(Callback callback)
Set the single Callback to use. Ignored if you use createClass().

Parameters:
callback - the callback to use for all methods
See Also:
setCallbacks(org.logicalcobwebs.cglib.proxy.Callback[])

setCallbacks

public void setCallbacks(Callback[] callbacks)
Set the array of callbacks to use. Ignored if you use createClass(). You must use a CallbackFilter to specify the index into this array for each method in the proxied class.

Parameters:
callbacks - the callback array
See Also:
setCallbackFilter(org.logicalcobwebs.cglib.proxy.CallbackFilter), setCallback(org.logicalcobwebs.cglib.proxy.Callback)

setUseFactory

public void setUseFactory(boolean useFactory)
Set whether the enhanced object instances should implement the Factory interface. This was added for tools that need for proxies to be more indistinguishable from their targets. Also, in some cases it may be necessary to disable the Factory interface to prevent code from changing the underlying callbacks.

Parameters:
useFactory - whether to implement Factory; default is true

setCallbackType

public void setCallbackType(java.lang.Class callbackType)
Set the single type of Callback to use. This may be used instead of setCallback(org.logicalcobwebs.cglib.proxy.Callback) when calling createClass(), since it may not be possible to have an array of actual callback instances.

Parameters:
callbackType - the type of callback to use for all methods
See Also:
setCallbackTypes(java.lang.Class[])

setCallbackTypes

public void setCallbackTypes(java.lang.Class[] callbackTypes)
Set the array of callback types to use. This may be used instead of setCallbacks(org.logicalcobwebs.cglib.proxy.Callback[]) when calling createClass(), since it may not be possible to have an array of actual callback instances. You must use a CallbackFilter to specify the index into this array for each method in the proxied class.

Parameters:
callbackTypes - the array of callback types

create

public java.lang.Object create()
Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance. Uses the no-arg constructor of the superclass.

Returns:
a new instance

create

public java.lang.Object create(java.lang.Class[] argumentTypes,
                               java.lang.Object[] arguments)
Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance. Uses the constructor of the superclass matching the argumentTypes parameter, with the given arguments.

Parameters:
argumentTypes - constructor signature
arguments - compatible wrapped arguments to pass to constructor
Returns:
a new instance

createClass

public java.lang.Class createClass()
Generate a new class if necessary and return it without creating a new instance. This ignores any callbacks that have been set. To create a new instance you will have to use reflection, and methods called during the constructor will not be intercepted. To avoid this problem, use the multi-arg create method.

See Also:
create(Class[], Object[])

createHelper

private java.lang.Object createHelper()

getDefaultClassLoader

protected java.lang.ClassLoader getDefaultClassLoader()
Specified by:
getDefaultClassLoader in class AbstractClassGenerator

generateClass

public void generateClass(ClassVisitor v)
                   throws java.lang.Exception
Throws:
java.lang.Exception

firstInstance

protected java.lang.Object firstInstance(java.lang.Class type)
                                  throws java.lang.Exception
Specified by:
firstInstance in class AbstractClassGenerator
Throws:
java.lang.Exception

nextInstance

protected java.lang.Object nextInstance(java.lang.Object instance)
Specified by:
nextInstance in class AbstractClassGenerator

createUsingReflection

private java.lang.Object createUsingReflection(java.lang.Class type)

create

public static java.lang.Object create(java.lang.Class type,
                                      Callback callback)
Helper method to create an intercepted object. For finer control over the generated instance, use a new instance of Enhancer instead of this static method.

Parameters:
type - class to extend or interface to implement
callback - the callback to use for all methods

create

public static java.lang.Object create(java.lang.Class superclass,
                                      java.lang.Class[] interfaces,
                                      Callback callback)
Helper method to create an intercepted object. For finer control over the generated instance, use a new instance of Enhancer instead of this static method.

Parameters:
type - class to extend or interface to implement
interfaces - array of interfaces to implement, or null
callback - the callback to use for all methods

create

public static java.lang.Object create(java.lang.Class superclass,
                                      java.lang.Class[] interfaces,
                                      CallbackFilter filter,
                                      Callback[] callbacks)
Helper method to create an intercepted object. For finer control over the generated instance, use a new instance of Enhancer instead of this static method.

Parameters:
type - class to extend or interface to implement
interfaces - array of interfaces to implement, or null
filter - the callback filter to use when generating a new class
callbacks - callback implementations to use for the enhanced object