Class Enhancer
- All Implemented Interfaces:
ClassGenerator
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
Nested ClassesModifier and TypeClassDescription(package private) static class
The idea of the class is to cache relevant java.lang.reflect instances so proxy-class can be instantiated faster that when usingReflectUtils.newInstance(Class, Class[], Object[])
andsetThreadCallbacks(Class, Callback[])
static interface
Internal interface, only public due to ClassLoader issues.Nested classes/interfaces inherited from class net.sf.cglib.core.AbstractClassGenerator
AbstractClassGenerator.ClassLoaderData, AbstractClassGenerator.Source
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final CallbackFilter
private Object[]
private Class[]
private static final Signature
private static final String
private static final org.objectweb.asm.Type
private static final org.objectweb.asm.Type
private static final String
AbstractClassGenerator.ClassLoaderData.generatedClasses
requires to keep cache key in a good shape (the keys should be up and running if the proxy class is alive), and one of the cache keys isCallbackFilter
.private Callback[]
private org.objectweb.asm.Type[]
private boolean
private static final String
private static final Signature
private Enhancer.EnhancerFactoryData
private Object
private static final org.objectweb.asm.Type
private static final String
private CallbackFilter
private static final Signature
private static final Signature
private static final org.objectweb.asm.Type
private static final org.objectweb.asm.Type
private boolean
private Class[]
private static final Enhancer.EnhancerKey
private static final Signature
private static final Signature
private static final org.objectweb.asm.Type
private Long
private static final Signature
private static final Signature
private static final Signature
private static final String
private static final Signature
private static final String
private static final Signature
private static final AbstractClassGenerator.Source
private static final String
private Class
private static final String
private static final org.objectweb.asm.Type
private static final Signature
private static final Signature
private boolean
private boolean
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptioncreate()
Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance.Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance.static Object
Helper method to create an intercepted object.static Object
create
(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) Helper method to create an intercepted object.static Object
Helper method to create an intercepted object.Generate a new class if necessary and return it without creating a new instance.private Object
private Object
createUsingReflection
(Class type) Instantiates a proxy instance and assigns callback values.private void
private void
private void
emitConstructors
(ClassEmitter ce, List constructors) private void
emitCurrentCallback
(CodeEmitter e, int index) private void
private void
emitGetCallback
(ClassEmitter ce, int[] keys) private void
private void
emitMethods
(ClassEmitter ce, List methods, List actualMethods) private void
private void
private void
emitNewInstanceMultiarg
(ClassEmitter ce, List constructors) private void
emitSetCallback
(ClassEmitter ce, int[] keys) private void
private void
private void
protected void
filterConstructors
(Class sc, List constructors) Filter the list of constructors from the superclass.protected Object
firstInstance
(Class type) This method should not be called in regular flow.protected Class
void
generateClass
(org.objectweb.asm.ClassVisitor v) private static String
getCallbackField
(int index) private int[]
private static Method
getCallbacksSetter
(Class type, String methodName) protected ClassLoader
static void
getMethods
(Class superclass, Class[] interfaces, List methods) Finds all of the methods that will be extended by an Enhancer-generated class using the specified superclass and interfaces.private static void
getMethods
(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic) protected ProtectionDomain
Returns the protection domain to use when defining the class.private org.objectweb.asm.Type
static boolean
isEnhanced
(Class type) Determine if a class was generated usingEnhancer
.protected Object
nextInstance
(Object instance) private void
static void
registerCallbacks
(Class generatedClass, Callback[] callbacks) Call this method to register theCallback
array to use before creating a new instance of the generated class via reflection.static void
registerStaticCallbacks
(Class generatedClass, Callback[] callbacks) Similar toregisterCallbacks(java.lang.Class, net.sf.cglib.proxy.Callback[])
, but suitable for use when multiple threads will be creating instances of the generated class.private Signature
void
setCallback
(Callback callback) Set the singleCallback
to use.void
setCallbackFilter
(CallbackFilter filter) Set theCallbackFilter
used to map the generated class' methods to a particular callback index.void
setCallbacks
(Callback[] callbacks) Set the array of callbacks to use.private static void
setCallbacksHelper
(Class type, Callback[] callbacks, String methodName) void
setCallbackType
(Class callbackType) Set the single type ofCallback
to use.void
setCallbackTypes
(Class[] callbackTypes) Set the array of callback types to use.void
setInterceptDuringConstruction
(boolean interceptDuringConstruction) Set whether methods called from within the proxy's constructer will be intercepted.void
setInterfaces
(Class[] interfaces) Set the interfaces to implement.void
setSerialVersionUID
(Long sUID) Insert a static serialVersionUID field into the generated class.void
setSuperclass
(Class superclass) Set the class which the generated class will extend.private static void
setThreadCallbacks
(Class type, Callback[] callbacks) void
setUseFactory
(boolean useFactory) Set whether the enhanced object instances should implement theFactory
interface.protected Object
unwrapCachedValue
(Object cached) private void
validate()
protected Object
wrapCachedClass
(Class klass) Methods inherited from class net.sf.cglib.core.AbstractClassGenerator
create, getAttemptLoad, getClassLoader, getClassName, getCurrent, getNamingPolicy, getStrategy, getUseCache, setAttemptLoad, setClassLoader, setNamePrefix, setNamingPolicy, setStrategy, setUseCache
-
Field Details
-
ALL_ZERO
-
SOURCE
-
KEY_FACTORY
-
BOUND_FIELD
- See Also:
-
FACTORY_DATA_FIELD
- See Also:
-
THREAD_CALLBACKS_FIELD
- See Also:
-
STATIC_CALLBACKS_FIELD
- See Also:
-
SET_THREAD_CALLBACKS_NAME
- See Also:
-
SET_STATIC_CALLBACKS_NAME
- See Also:
-
CONSTRUCTED_FIELD
- See Also:
-
CALLBACK_FILTER_FIELD
AbstractClassGenerator.ClassLoaderData.generatedClasses
requires to keep cache key in a good shape (the keys should be up and running if the proxy class is alive), and one of the cache keys isCallbackFilter
. That is why the generated class contains static field that keeps strong reference to thefilter
.This dance achieves two goals: ensures generated class is reusable and available through generatedClasses cache, and it enables to unload classloader and the related
CallbackFilter
in case user does not need that- See Also:
-
OBJECT_TYPE
private static final org.objectweb.asm.Type OBJECT_TYPE -
FACTORY
private static final org.objectweb.asm.Type FACTORY -
ILLEGAL_STATE_EXCEPTION
private static final org.objectweb.asm.Type ILLEGAL_STATE_EXCEPTION -
ILLEGAL_ARGUMENT_EXCEPTION
private static final org.objectweb.asm.Type ILLEGAL_ARGUMENT_EXCEPTION -
THREAD_LOCAL
private static final org.objectweb.asm.Type THREAD_LOCAL -
CALLBACK
private static final org.objectweb.asm.Type CALLBACK -
CALLBACK_ARRAY
private static final org.objectweb.asm.Type CALLBACK_ARRAY -
CSTRUCT_NULL
-
SET_THREAD_CALLBACKS
-
SET_STATIC_CALLBACKS
-
NEW_INSTANCE
-
MULTIARG_NEW_INSTANCE
-
SINGLE_NEW_INSTANCE
-
SET_CALLBACK
-
GET_CALLBACK
-
SET_CALLBACKS
-
GET_CALLBACKS
-
THREAD_LOCAL_GET
-
THREAD_LOCAL_SET
-
BIND_CALLBACKS
-
currentData
-
currentKey
-
interfaces
-
filter
-
callbacks
-
callbackTypes
private org.objectweb.asm.Type[] callbackTypes -
validateCallbackTypes
private boolean validateCallbackTypes -
classOnly
private boolean classOnly -
superclass
-
argumentTypes
-
arguments
-
useFactory
private boolean useFactory -
serialVersionUID
-
interceptDuringConstruction
private boolean interceptDuringConstruction
-
-
Constructor Details
-
Enhancer
public Enhancer()Create a newEnhancer
. A newEnhancer
object should be used for each generated object, and should not be shared across threads. To create additional instances of a generated class, use theFactory
interface.- See Also:
-
-
Method Details
-
setSuperclass
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
Set the interfaces to implement. TheFactory
interface will always be implemented regardless of what is specified here.- Parameters:
interfaces
- array of interfaces to implement, or null- See Also:
-
setCallbackFilter
Set theCallbackFilter
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:
-
setCallback
Set the singleCallback
to use. Ignored if you usecreateClass()
.- Parameters:
callback
- the callback to use for all methods- See Also:
-
setCallbacks
Set the array of callbacks to use. Ignored if you usecreateClass()
. You must use aCallbackFilter
to specify the index into this array for each method in the proxied class.- Parameters:
callbacks
- the callback array- See Also:
-
setUseFactory
public void setUseFactory(boolean useFactory) Set whether the enhanced object instances should implement theFactory
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 theFactory
interface to prevent code from changing the underlying callbacks.- Parameters:
useFactory
- whether to implementFactory
; default istrue
-
setInterceptDuringConstruction
public void setInterceptDuringConstruction(boolean interceptDuringConstruction) Set whether methods called from within the proxy's constructer will be intercepted. The default value is true. Unintercepted methods will call the method of the proxy's base class, if it exists.- Parameters:
interceptDuringConstruction
- whether to intercept methods called from the constructor
-
setCallbackType
Set the single type ofCallback
to use. This may be used instead ofsetCallback(net.sf.cglib.proxy.Callback)
when callingcreateClass()
, 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
Set the array of callback types to use. This may be used instead ofsetCallbacks(net.sf.cglib.proxy.Callback[])
when callingcreateClass()
, since it may not be possible to have an array of actual callback instances. You must use aCallbackFilter
to specify the index into this array for each method in the proxied class.- Parameters:
callbackTypes
- the array of callback types
-
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
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 theargumentTypes
parameter, with the given arguments.- Parameters:
argumentTypes
- constructor signaturearguments
- compatible wrapped arguments to pass to constructor- Returns:
- a new instance
-
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-argcreate
method.- See Also:
-
setSerialVersionUID
Insert a static serialVersionUID field into the generated class.- Parameters:
sUID
- the field value, or null to avoid generating field.
-
preValidate
private void preValidate() -
validate
private void validate() -
createHelper
-
generate
- Overrides:
generate
in classAbstractClassGenerator
-
getDefaultClassLoader
- Specified by:
getDefaultClassLoader
in classAbstractClassGenerator
-
getProtectionDomain
Description copied from class:AbstractClassGenerator
Returns the protection domain to use when defining the class.Default implementation returns
null
for using a default protection domain. Sub-classes may override to use a more specific protection domain.- Overrides:
getProtectionDomain
in classAbstractClassGenerator
- Returns:
- the protection domain (
null
for using a default)
-
rename
-
getMethods
Finds all of the methods that will be extended by an Enhancer-generated class using the specified superclass and interfaces. This can be useful in building a list of Callback objects. The methods are added to the end of the given list. Due to the subclassing nature of the classes generated by Enhancer, the methods are guaranteed to be non-static, non-final, and non-private. Each method signature will only occur once, even if it occurs in multiple classes.- Parameters:
superclass
- the class that will be extended, or nullinterfaces
- the list of interfaces that will be implemented, or nullmethods
- the list into which to copy the applicable methods
-
getMethods
-
generateClass
- Throws:
Exception
-
filterConstructors
Filter the list of constructors from the superclass. The constructors which remain will be included in the generated class. The default implementation is to filter out all private constructors, but subclasses may extend Enhancer to override this behavior.- Parameters:
sc
- the superclassconstructors
- the list of all declared constructors from the superclass- Throws:
IllegalArgumentException
- if there are no non-private constructors
-
firstInstance
This method should not be called in regular flow. Technically speakingwrapCachedClass(Class)
usesEnhancer.EnhancerFactoryData
as a cache value, and the latter enables faster instantiation than plain old reflection lookup and invoke. This method is left intact for backward compatibility reasons: just in case it was ever used.- Specified by:
firstInstance
in classAbstractClassGenerator
- Parameters:
type
- class to instantiate- Returns:
- newly created proxy instance
- Throws:
Exception
- if something goes wrong
-
nextInstance
- Specified by:
nextInstance
in classAbstractClassGenerator
-
wrapCachedClass
- Overrides:
wrapCachedClass
in classAbstractClassGenerator
-
unwrapCachedValue
- Overrides:
unwrapCachedValue
in classAbstractClassGenerator
-
registerCallbacks
Call this method to register theCallback
array to use before creating a new instance of the generated class via reflection. If you are using an instance ofEnhancer
or theFactory
interface to create new instances, this method is unnecessary. Its primary use is for when you want to cache and reuse a generated class yourself, and the generated class does not implement theFactory
interface.Note that this method only registers the callbacks on the current thread. If you want to register callbacks for instances created by multiple threads, use
registerStaticCallbacks(java.lang.Class, net.sf.cglib.proxy.Callback[])
.The registered callbacks are overwritten and subsequently cleared when calling any of the
create
methods (such ascreate()
), or anyFactory
newInstance
method. Otherwise they are not cleared, and you should be careful to set them back tonull
after creating new instances via reflection if memory leakage is a concern.- Parameters:
generatedClass
- a class previously created byEnhancer
callbacks
- the array of callbacks to use when instances of the generated class are created- See Also:
-
registerStaticCallbacks
Similar toregisterCallbacks(java.lang.Class, net.sf.cglib.proxy.Callback[])
, but suitable for use when multiple threads will be creating instances of the generated class. The thread-level callbacks will always override the static callbacks. Static callbacks are never cleared.- Parameters:
generatedClass
- a class previously created byEnhancer
callbacks
- the array of callbacks to use when instances of the generated class are created
-
isEnhanced
Determine if a class was generated usingEnhancer
.- Parameters:
type
- any class- Returns:
- whether the class was generated using
Enhancer
-
setThreadCallbacks
-
setCallbacksHelper
-
getCallbacksSetter
private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException - Throws:
NoSuchMethodException
-
createUsingReflection
Instantiates a proxy instance and assigns callback values. Implementation detail: java.lang.reflect instances are not cached, so this method should not be used on a hot path. This method is used whenAbstractClassGenerator.setUseCache(boolean)
is set tofalse
.- Parameters:
type
- class to instantiate- Returns:
- newly created instance
-
create
Helper method to create an intercepted object. For finer control over the generated instance, use a new instance ofEnhancer
instead of this static method.- Parameters:
type
- class to extend or interface to implementcallback
- the callback to use for all methods
-
create
Helper method to create an intercepted object. For finer control over the generated instance, use a new instance ofEnhancer
instead of this static method.- Parameters:
superclass
- class to extend or interface to implementinterfaces
- array of interfaces to implement, or nullcallback
- the callback to use for all methods
-
create
public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) Helper method to create an intercepted object. For finer control over the generated instance, use a new instance ofEnhancer
instead of this static method.- Parameters:
superclass
- class to extend or interface to implementinterfaces
- array of interfaces to implement, or nullfilter
- the callback filter to use when generating a new classcallbacks
- callback implementations to use for the enhanced object
-
emitDefaultConstructor
-
emitConstructors
-
getCallbackKeys
private int[] getCallbackKeys() -
emitGetCallback
-
emitSetCallback
-
emitSetCallbacks
-
emitGetCallbacks
-
emitNewInstanceCallbacks
-
getThisType
-
emitCommonNewInstance
-
emitNewInstanceCallback
-
emitNewInstanceMultiarg
-
emitMethods
-
emitSetThreadCallbacks
-
emitSetStaticCallbacks
-
emitCurrentCallback
-
emitBindCallbacks
-
getCallbackField
-