Class ScriptFactoryPostProcessor
- All Implemented Interfaces:
Aware
,BeanClassLoaderAware
,BeanFactoryAware
,BeanPostProcessor
,InstantiationAwareBeanPostProcessor
,SmartInstantiationAwareBeanPostProcessor
,DisposableBean
,ResourceLoaderAware
,Ordered
BeanPostProcessor
that
handles ScriptFactory
definitions,
replacing each factory with the actual scripted Java object generated by it.
This is similar to the
FactoryBean
mechanism, but is
specifically tailored for scripts and not built into Spring's core
container itself but rather implemented as an extension.
NOTE: The most important characteristic of this post-processor
is that constructor arguments are applied to the
ScriptFactory
instance
while bean property values are applied to the generated scripted object.
Typically, constructor arguments include a script source locator and
potentially script interfaces, while bean property values include
references and config values to inject into the scripted object itself.
The following ScriptFactoryPostProcessor
will automatically
be applied to the two
ScriptFactory
definitions below.
At runtime, the actual scripted objects will be exposed for
"bshMessenger" and "groovyMessenger", rather than the
ScriptFactory
instances. Both of
those are supposed to be castable to the example's Messenger
interfaces here.
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/> <bean id="bshMessenger" class="org.springframework.scripting.bsh.BshScriptFactory"> <constructor-arg value="classpath:mypackage/Messenger.bsh"/> <constructor-arg value="mypackage.Messenger"/> <property name="message" value="Hello World!"/> </bean> <bean id="groovyMessenger" class="org.springframework.scripting.groovy.GroovyScriptFactory"> <constructor-arg value="classpath:mypackage/Messenger.groovy"/> <property name="message" value="Hello World!"/> </bean>
NOTE: Please note that the above excerpt from a Spring
XML bean definition file uses just the <bean/>-style syntax
(in an effort to illustrate using the ScriptFactoryPostProcessor
itself).
In reality, you would never create a <bean/> definition for a
ScriptFactoryPostProcessor
explicitly; rather you would import the
tags from the 'lang'
namespace and simply create scripted
beans using the tags in that namespace... as part of doing so, a
ScriptFactoryPostProcessor
will implicitly be created for you.
The Spring reference documentation contains numerous examples of using
tags in the 'lang'
namespace; by way of an example, find below
a Groovy-backed bean defined using the 'lang:groovy'
tag.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang"> <!-- this is the bean definition for the Groovy-backed Messenger implementation --> <lang:groovy id="messenger" script-source="classpath:Messenger.groovy"> <lang:property name="message" value="I Can Do The Frug" /> </lang:groovy> <!-- an otherwise normal bean that will be injected by the Groovy-backed Messenger --> <bean id="bookingService" class="x.y.DefaultBookingService"> <property name="messenger" ref="messenger" /> </bean> </beans>
- Since:
- 2.0
- Author:
- Juergen Hoeller, Rob Harrop, Rick Evans, Mark Fisher, Sam Brannen
-
Field Summary
Modifier and TypeFieldDescriptionstatic final String
TheResource
-style prefix that denotes an inline script.static final String
Thelanguage
attribute.protected final Log
Logger available to subclasses.static final String
TheproxyTargetClass
attribute.static final String
TherefreshCheckDelay
attribute.Fields inherited from interface org.springframework.core.Ordered
HIGHEST_PRECEDENCE, LOWEST_PRECEDENCE
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionprotected ScriptSource
convertToScriptSource
(String beanName, String scriptSourceLocator, ResourceLoader resourceLoader) Convert the given script source locator to a ScriptSource instance.protected Class<?>
createCompositeInterface
(Class<?>[] interfaces) Create a composite interface Class for the given interfaces, implementing the given interfaces in one single Class.protected Class<?>
createConfigInterface
(BeanDefinition bd, Class<?>[] interfaces) Create a config interface for the given bean definition, defining setter methods for the defined property values as well as an init method and a destroy method (if defined).protected Object
createRefreshableProxy
(TargetSource ts, Class<?>[] interfaces, boolean proxyTargetClass) Create a refreshable proxy for the given AOP TargetSource.protected BeanDefinition
createScriptedObjectBeanDefinition
(BeanDefinition bd, String scriptFactoryBeanName, ScriptSource scriptSource, Class<?>[] interfaces) Create a bean definition for the scripted object, based on the given script definition, extracting the definition data that is relevant for the scripted object (that is, everything but bean class and constructor arguments).protected BeanDefinition
Create a ScriptFactory bean definition based on the given script definition, extracting only the definition data that is relevant for the ScriptFactory (that is, only bean class and constructor arguments).void
destroy()
Destroy the inner bean factory (used for scripts) on shutdown.int
getOrder()
Get the order value of this object.protected ScriptSource
getScriptSource
(String beanName, String scriptSourceLocator) Obtain a ScriptSource for the given bean, lazily creating it if not cached already.postProcessBeforeInstantiation
(Class<?> beanClass, String beanName) Apply this BeanPostProcessor before the target bean gets instantiated.postProcessProperties
(PropertyValues pvs, Object bean, String beanName) Post-process the given property values before the factory applies them to the given bean.Class<?>
predictBeanType
(Class<?> beanClass, String beanName) Predict the type of the bean to be eventually returned from this processor'sInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(java.lang.Class<?>, java.lang.String)
callback.protected void
prepareScriptBeans
(BeanDefinition bd, String scriptFactoryBeanName, String scriptedObjectBeanName) Prepare the script beans in the internal BeanFactory that this post-processor uses.protected boolean
resolveProxyTargetClass
(BeanDefinition beanDefinition) protected long
resolveRefreshCheckDelay
(BeanDefinition beanDefinition) Get the refresh check delay for the givenScriptFactory
BeanDefinition
.void
setBeanClassLoader
(ClassLoader classLoader) Callback that supplies the beanclass loader
to a bean instance.void
setBeanFactory
(BeanFactory beanFactory) Callback that supplies the owning factory to a bean instance.void
setDefaultProxyTargetClass
(boolean defaultProxyTargetClass) Flag to signal that refreshable proxies should be created to proxy the target class not its interfaces.void
setDefaultRefreshCheckDelay
(long defaultRefreshCheckDelay) Set the delay between refresh checks, in milliseconds.void
setResourceLoader
(ResourceLoader resourceLoader) Set the ResourceLoader that this object runs in.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods inherited from interface org.springframework.beans.factory.config.BeanPostProcessor
postProcessAfterInitialization, postProcessBeforeInitialization
Methods inherited from interface org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
postProcessAfterInstantiation
Methods inherited from interface org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
determineBeanType, determineCandidateConstructors, getEarlyBeanReference
-
Field Details
-
INLINE_SCRIPT_PREFIX
TheResource
-style prefix that denotes an inline script.An inline script is a script that is defined right there in the (typically XML) configuration, as opposed to being defined in an external file.
- See Also:
-
REFRESH_CHECK_DELAY_ATTRIBUTE
TherefreshCheckDelay
attribute. -
PROXY_TARGET_CLASS_ATTRIBUTE
TheproxyTargetClass
attribute. -
LANGUAGE_ATTRIBUTE
Thelanguage
attribute. -
logger
Logger available to subclasses.
-
-
Constructor Details
-
ScriptFactoryPostProcessor
public ScriptFactoryPostProcessor()
-
-
Method Details
-
setDefaultRefreshCheckDelay
public void setDefaultRefreshCheckDelay(long defaultRefreshCheckDelay) Set the delay between refresh checks, in milliseconds. Default is -1, indicating no refresh checks at all.Note that an actual refresh will only happen when the
ScriptSource
indicates that it has been modified.- See Also:
-
setDefaultProxyTargetClass
public void setDefaultProxyTargetClass(boolean defaultProxyTargetClass) Flag to signal that refreshable proxies should be created to proxy the target class not its interfaces.- Parameters:
defaultProxyTargetClass
- the flag value to set
-
setBeanClassLoader
Description copied from interface:BeanClassLoaderAware
Callback that supplies the beanclass loader
to a bean instance.Invoked after the population of normal bean properties but before an initialization callback such as
InitializingBean's
InitializingBean.afterPropertiesSet()
method or a custom init-method.- Specified by:
setBeanClassLoader
in interfaceBeanClassLoaderAware
- Parameters:
classLoader
- the owning class loader
-
setBeanFactory
Description copied from interface:BeanFactoryAware
Callback that supplies the owning factory to a bean instance.Invoked after the population of normal bean properties but before an initialization callback such as
InitializingBean.afterPropertiesSet()
or a custom init-method.- Specified by:
setBeanFactory
in interfaceBeanFactoryAware
- Parameters:
beanFactory
- owning BeanFactory (nevernull
). The bean can immediately call methods on the factory.- See Also:
-
setResourceLoader
Description copied from interface:ResourceLoaderAware
Set the ResourceLoader that this object runs in.This might be a ResourcePatternResolver, which can be checked through
instanceof ResourcePatternResolver
. See also theResourcePatternUtils.getResourcePatternResolver
method.Invoked after population of normal bean properties but before an init callback like InitializingBean's
afterPropertiesSet
or a custom init-method. Invoked before ApplicationContextAware'ssetApplicationContext
.- Specified by:
setResourceLoader
in interfaceResourceLoaderAware
- Parameters:
resourceLoader
- the ResourceLoader object to be used by this object- See Also:
-
getOrder
public int getOrder()Description copied from interface:Ordered
Get the order value of this object.Higher values are interpreted as lower priority. As a consequence, the object with the lowest value has the highest priority (somewhat analogous to Servlet
load-on-startup
values).Same order values will result in arbitrary sort positions for the affected objects.
-
predictBeanType
Description copied from interface:SmartInstantiationAwareBeanPostProcessor
Predict the type of the bean to be eventually returned from this processor'sInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(java.lang.Class<?>, java.lang.String)
callback.The default implementation returns
null
. Specific implementations should try to predict the bean type as far as known/cached already, without extra processing steps.- Specified by:
predictBeanType
in interfaceSmartInstantiationAwareBeanPostProcessor
- Parameters:
beanClass
- the raw class of the beanbeanName
- the name of the bean- Returns:
- the type of the bean, or
null
if not predictable
-
postProcessProperties
Description copied from interface:InstantiationAwareBeanPostProcessor
Post-process the given property values before the factory applies them to the given bean.The default implementation returns the given
pvs
as-is.- Specified by:
postProcessProperties
in interfaceInstantiationAwareBeanPostProcessor
- Parameters:
pvs
- the property values that the factory is about to apply (nevernull
)bean
- the bean instance created, but whose properties have not yet been setbeanName
- the name of the bean- Returns:
- the actual property values to apply to the given bean (can be the passed-in
PropertyValues instance), or
null
to skip property population
-
postProcessBeforeInstantiation
Description copied from interface:InstantiationAwareBeanPostProcessor
Apply this BeanPostProcessor before the target bean gets instantiated. The returned bean object may be a proxy to use instead of the target bean, effectively suppressing default instantiation of the target bean.If a non-null object is returned by this method, the bean creation process will be short-circuited. The only further processing applied is the
BeanPostProcessor.postProcessAfterInitialization(java.lang.Object, java.lang.String)
callback from the configuredBeanPostProcessors
.This callback will be applied to bean definitions with their bean class, as well as to factory-method definitions in which case the returned bean type will be passed in here.
Post-processors may implement the extended
SmartInstantiationAwareBeanPostProcessor
interface in order to predict the type of the bean object that they are going to return here.The default implementation returns
null
.- Specified by:
postProcessBeforeInstantiation
in interfaceInstantiationAwareBeanPostProcessor
- Parameters:
beanClass
- the class of the bean to be instantiatedbeanName
- the name of the bean- Returns:
- the bean object to expose instead of a default instance of the target bean,
or
null
to proceed with default instantiation - See Also:
-
prepareScriptBeans
protected void prepareScriptBeans(BeanDefinition bd, String scriptFactoryBeanName, String scriptedObjectBeanName) Prepare the script beans in the internal BeanFactory that this post-processor uses. Each original bean definition will be split into a ScriptFactory definition and a scripted object definition.- Parameters:
bd
- the original bean definition in the main BeanFactoryscriptFactoryBeanName
- the name of the internal ScriptFactory beanscriptedObjectBeanName
- the name of the internal scripted object bean
-
resolveRefreshCheckDelay
Get the refresh check delay for the givenScriptFactory
BeanDefinition
. If theBeanDefinition
has ametadata attribute
under the keyREFRESH_CHECK_DELAY_ATTRIBUTE
which is a validNumber
type, then this value is used. Otherwise, thedefaultRefreshCheckDelay
value is used.- Parameters:
beanDefinition
- the BeanDefinition to check- Returns:
- the refresh check delay
-
resolveProxyTargetClass
-
createScriptFactoryBeanDefinition
Create a ScriptFactory bean definition based on the given script definition, extracting only the definition data that is relevant for the ScriptFactory (that is, only bean class and constructor arguments).- Parameters:
bd
- the full script bean definition- Returns:
- the extracted ScriptFactory bean definition
- See Also:
-
getScriptSource
Obtain a ScriptSource for the given bean, lazily creating it if not cached already.- Parameters:
beanName
- the name of the scripted beanscriptSourceLocator
- the script source locator associated with the bean- Returns:
- the corresponding ScriptSource instance
- See Also:
-
convertToScriptSource
protected ScriptSource convertToScriptSource(String beanName, String scriptSourceLocator, ResourceLoader resourceLoader) Convert the given script source locator to a ScriptSource instance.By default, supported locators are Spring resource locations (such as "file:C:/myScript.bsh" or "classpath:myPackage/myScript.bsh") and inline scripts ("inline:myScriptText...").
- Parameters:
beanName
- the name of the scripted beanscriptSourceLocator
- the script source locatorresourceLoader
- the ResourceLoader to use (if necessary)- Returns:
- the ScriptSource instance
-
createConfigInterface
Create a config interface for the given bean definition, defining setter methods for the defined property values as well as an init method and a destroy method (if defined).This implementation creates the interface via CGLIB's InterfaceMaker, determining the property types from the given interfaces (as far as possible).
- Parameters:
bd
- the bean definition (property values etc) to create a config interface forinterfaces
- the interfaces to check against (might define getters corresponding to the setters we're supposed to generate)- Returns:
- the config interface
- See Also:
-
createCompositeInterface
Create a composite interface Class for the given interfaces, implementing the given interfaces in one single Class.The default implementation builds a JDK proxy class for the given interfaces.
- Parameters:
interfaces
- the interfaces to merge- Returns:
- the merged interface as Class
- See Also:
-
createScriptedObjectBeanDefinition
protected BeanDefinition createScriptedObjectBeanDefinition(BeanDefinition bd, String scriptFactoryBeanName, ScriptSource scriptSource, @Nullable Class<?>[] interfaces) Create a bean definition for the scripted object, based on the given script definition, extracting the definition data that is relevant for the scripted object (that is, everything but bean class and constructor arguments).- Parameters:
bd
- the full script bean definitionscriptFactoryBeanName
- the name of the internal ScriptFactory beanscriptSource
- the ScriptSource for the scripted beaninterfaces
- the interfaces that the scripted bean is supposed to implement- Returns:
- the extracted ScriptFactory bean definition
- See Also:
-
createRefreshableProxy
protected Object createRefreshableProxy(TargetSource ts, @Nullable Class<?>[] interfaces, boolean proxyTargetClass) Create a refreshable proxy for the given AOP TargetSource.- Parameters:
ts
- the refreshable TargetSourceinterfaces
- the proxy interfaces (may benull
to indicate proxying of all interfaces implemented by the target class)- Returns:
- the generated proxy
- See Also:
-
destroy
public void destroy()Destroy the inner bean factory (used for scripts) on shutdown.- Specified by:
destroy
in interfaceDisposableBean
-