public interface ExtensionHandler
ExtensionHandlers contain the logic for handling calls to extension
interfaces of IBeans. They are used by ProxyIBeanFactory for internal
extension interfaces but also for any custom extension interface. See
IBeanFactory for general descriptions about extension interfaces.
ExtensionHandler itself is just an interface and each extension
interface requires its individual implementation of ExtensionHandler.
For example built in extension interface NullSafe uses its matching
handler implementation NullSafeHandler.
If you are just using existing extension interfaces provided by the IBean
framework you will normally not get in touch with ExtensionHandlers.
They become relevant if you want to implement your own extension interface.
In this case you need to implement ExtensionHandler, bundle it with
the extension interface using ExtensionSupport and configure it in
the ProxyIBeanFactory
(ProxyIBeanFactory.Builder.withInterfaceSupport(ExtensionSupport)).
ExtensionHandler implementations need to be instanciated by the
IBeanFactory. Therefore they need to have a public constructor
without arguments. The implementation class itself also needs to be public.
To increase performance by avoiding unnecessary instance creation two types
of ExtensionHandlers were introduced, stateful and stateless
handlers. Stateful handlers are used for extension interfaces that enrich the
state of an IBean. Therefore each IBean instance holds its individual handler
instance. For stateless ExtensionHandlers only one instances is
created initially and that instance serves all interface calls to any
bean.
For example extension interface ModificationAware requires a stateful
handler as the handler needs to store a dirty flag internally, whereas
NullSafe can run with a stateless handler.
Whether stateful or stateless is determined in ExtensionSupport when
configuring a handler for a factory.
An IBean receives three types of method calls,
handleExtendedInterfaceCall(IBeanContext, IBeanFieldAccess, Object, Method, Object[]).
An implementation may override
interceptGetterCall(IBeanContext, IBeanFieldMetaInfo, Object, Object)
or
interceptSetterCall(IBeanContext, IBeanFieldMetaInfo, Object, Object)
for hooking into getter and setter calls.
Handlers for built-in extension interfaces do not implement
ExtensionHandler directly but extend either
StatefulExtensionHandler or StatelessExtensionHandler. This
is recommended for custom handlers as well.
| Modifier and Type | Method and Description |
|---|---|
Object |
handleExtendedInterfaceCall(IBeanContext<?> context,
IBeanFieldAccess bean,
Object proxyInstance,
Method method,
Object[] params)
Handles all calls to methods of its related extension interface.
|
default Object |
interceptGetterCall(IBeanContext<?> context,
IBeanFieldMetaInfo fieldMeta,
Object returnValue,
Object proxyInstance)
Called as an optional hook with every getter call on an IBean.
|
default Object |
interceptSetterCall(IBeanContext<?> context,
IBeanFieldMetaInfo fieldMeta,
Object newValue,
Object proxyInstance)
Called as an optional hook with every setter call on an IBean.
|
default void |
onInitStateful(Object proxyInstance,
IBeanTypeMetaInfo<?> metaInfo,
IBeanFactory factory)
Initialization method for stateful handlers that is called after
initialization of the IBean.
|
Object handleExtendedInterfaceCall(IBeanContext<?> context, IBeanFieldAccess bean, Object proxyInstance, Method method, Object[] params) throws Throwable
ExtensionHandler implementations, all other methods are optional
and have default implementations.
When a method of an extension interface is called on an IBean the bean
looks up the matching ExtensionHandler for the extension and
calls this method on the handler. As the IBean implementation in this
package is based on Java proxies handleExtendedInterfaceCall
is very similar to
InvocationHandler.invoke(Object, Method, Object[]) just extended
by some IBean scope information. The last three parameters
(proxyInstance, method and params)
are simply passed through from the InvocationHandler of the
IBean. Therefore when implementing this method you need to follow the
same rules that you need to consider when implementing an
InvocationHandler, for example in terms of thrown exceptions or
return types.
Bean values can be read or manipulated by this method. Used the passed
bean parameter for doing so.
The return value or exception coming out of this method will be the return value or exception returned from the extension method call.
context - provides meta information about the beanbean - allows this method to read or change field values of the IBeanproxyInstance - the IBean instance object (see
InvocationHandler.invoke(Object, Method, Object[]) for
more details)method - the Method of the extension interface that was called
on the IBean (see
InvocationHandler.invoke(Object, Method, Object[]) for
more details)params - the parameters passed to the extension method call (see
InvocationHandler.invoke(Object, Method, Object[]) for
more details)null if the return type is
void. (see
InvocationHandler.invoke(Object, Method, Object[]) for
more details)Throwable - can be any Error, RuntimeException or checked
exception that is definied in the signature of the extension
method. (see
InvocationHandler.invoke(Object, Method, Object[])
for more details)default Object interceptGetterCall(IBeanContext<?> context, IBeanFieldMetaInfo fieldMeta, Object returnValue, Object proxyInstance)
ExtensionHandler can implement this method to hook into the
getter call. It can just peak on the return value or it can even change
it or throw an exception.
When you have several extension handlers registered for an IBean type the
intercept calls will be called in the order in which the handlers are
registered in the ProxyIBeanFactory. See also
ProxyIBeanFactory.Builder.withInterfaceSupport(ExtensionSupport).
The default implementation just returns returnValue.
context - provides meta information about the IBeanfieldMeta - provides meta information about the field related to the
getterreturnValue - the current return value of the getter. This must not match to
the field value of the IBean as the value might have already
been changed by intercept calls from other handlersproxyInstance - the IBean instance itselfreturnValuedefault Object interceptSetterCall(IBeanContext<?> context, IBeanFieldMetaInfo fieldMeta, Object newValue, Object proxyInstance)
ExtensionHandler can implement this method to hook into the
setter call. It can just peak on the new value or it can even change it
or throw an exception.
When you have several extension handlers registered for an IBean type the
intercept calls will be called in the order in which the handlers are
registered in the ProxyIBeanFactory. See also
ProxyIBeanFactory.Builder.withInterfaceSupport(ExtensionSupport).
The default implementation just returns newValue.
context - provides meta information about the IBeanfieldMeta - provides meta information about the field related to the
setternewValue - the current new value of the field. This must not match to the
initial value given in the setter call of the IBean as the
value might have already been changed by intercept calls from
other handlersproxyInstance - the IBean instance itselfnewValuedefault void onInitStateful(Object proxyInstance, IBeanTypeMetaInfo<?> metaInfo, IBeanFactory factory)
ExtensionHandler implementation is created for
each new IBean. After the IBean itself and all handlers created this
method is called on all stateful handlers. This method should therefore
be overwritten if a handler needs some initialization after creation.
The default implementation does nothing.
proxyInstance - the IBean instancemetaInfo - meta information about the IBeanfactory - the factory that creates the IBean instance