public class BeansWrapperBuilder extends BeansWrapperConfiguration
BeansWrapper
singleton instance that's already configured as specified in the properties of
this object; this is recommended over using the BeansWrapper
constructors. The returned instance can't be
further configured (it's write protected).
The builder meant to be used as a drop-away object (not stored in a field), like in this example:
BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build();
Or, a more complex example:
// Create the builder: BeansWrapperBuilder builder = new BeansWrapperBuilder(Configuration.VERSION_2_3_21); // Set desired BeansWrapper configuration properties: builder.setUseMoldeCache(true); builder.setExposeFields(true); // Get the singleton: BeansWrapper beansWrapper = builder.build(); // You don't need the builder anymore.
Despite that builders aren't meant to be used as long-lived objects (singletons), the builder is thread-safe after you have stopped calling its setters and it was safely published (see JSR 133) to other threads. This can be useful if you have to put the builder into an IoC container, rather than the singleton it produces.
The main benefit of using a builder instead of a BeansWrapper
constructor is that this way the
internal object wrapping-related caches (most notably the class introspection cache) will come from a global,
JVM-level (more precisely, freemarker.jar
-class-loader-level) cache. Also the BeansWrapper
singletons
themselves are stored in this global cache. Some of the wrapping-related caches are expensive to build and can take
significant amount of memory. Using builders, components that use FreeMarker will share BeansWrapper
instances and said caches even if they use separate FreeMarker Configuration
-s. (Many Java libraries use
FreeMarker internally, so Configuration
sharing is not an option.)
Note that the returned BeansWrapper
instances are only weak-referenced from inside the builder mechanism,
so singletons are garbage collected when they go out of usage, just like non-singletons.
About the object wrapping-related caches:
Class introspection cache: Stores information about classes that once had to be wrapped. The cache is
stored in the static fields of certain FreeMarker classes. Thus, if you have two BeansWrapper
instances, they might share the same class introspection cache. But if you have two
freemarker.jar
-s (typically, in two Web Application's WEB-INF/lib
directories), those won't
share their caches (as they don't share the same FreeMarker classes).
Also, currently there's a separate cache for each permutation of the property values that influence class
introspection: expose_fields
and
exposure_level
. So only BeansWrapper
where those
properties are the same may share class introspection caches among each other.
Model caches: These are local to a BeansWrapper
. BeansWrapperBuilder
returns the same
BeansWrapper
instance for equivalent properties (unless the existing instance was garbage collected
and thus a new one had to be created), hence these caches will be re-used too. BeansWrapper
instances
are cached in the static fields of FreeMarker too, but there's a separate cache for each
Thread Context Class Loader, which in a servlet container practically means a separate cache for each Web
Application (each servlet context). (This is like so because for resolving class names to classes FreeMarker
uses the Thread Context Class Loader, so the result of the resolution can be different for different
Thread Context Class Loaders.) The model caches are:
Static model caches: These are used by the hash returned by BeansWrapper.getEnumModels()
and
BeansWrapper.getStaticModels()
, for caching TemplateModel
-s for the static methods/fields
and Java 5 enums that were accessed through them. To use said hashes, you have to put them
explicitly into the data-model or expose them to the template explicitly otherwise, so in most applications
these caches aren't unused.
Instance model cache: By default off (see BeansWrapper.setUseCache(boolean)
). Caches the
TemplateModel
-s for all Java objects that were accessed from templates.
Note that what this method documentation says about BeansWrapper
also applies to
DefaultObjectWrapperBuilder
.
classIntrospectorFactory
Constructor and Description |
---|
BeansWrapperBuilder(Version incompatibleImprovements)
|
Modifier and Type | Method and Description |
---|---|
BeansWrapper |
build()
Returns a
BeansWrapper instance that matches the settings of this builder. |
clone, equals, getDefaultDateType, getExposeFields, getExposureLevel, getIncompatibleImprovements, getMethodAppearanceFineTuner, getOuterIdentity, getUseModelCache, hashCode, isSimpleMapWrapper, isStrict, setDefaultDateType, setExposeFields, setExposureLevel, setMethodAppearanceFineTuner, setOuterIdentity, setSimpleMapWrapper, setStrict, setUseModelCache
public BeansWrapperBuilder(Version incompatibleImprovements)
public BeansWrapper build()
BeansWrapper
instance that matches the settings of this builder. This will be possibly a
singleton that is also in use elsewhere, not necessarily a new object.