public class ProxyFactoryBean extends ProxyCreatorSupport implements FactoryBean<java.lang.Object>, BeanClassLoaderAware, BeanFactoryAware
FactoryBean
implementation that builds an
AOP proxy based on beans in Spring BeanFactory
.
MethodInterceptors
and
Advisors
are identified by a list of bean
names in the current bean factory, specified through the "interceptorNames" property.
The last entry in the list can be the name of a target bean or a
TargetSource
; however, it is normally preferable
to use the "targetName"/"target"/"targetSource" properties instead.
Global interceptors and advisors can be added at the factory level. The specified
ones are expanded in an interceptor list where an "xxx*" entry is included in the
list, matching the given prefix with the bean names (e.g. "global*" would match
both "globalBean1" and "globalBean2", "*" all defined interceptors). The matching
interceptors get applied according to their returned order value, if they implement
the Ordered
interface.
Creates a JDK proxy when proxy interfaces are given, and a CGLIB proxy for the actual target class if not. Note that the latter will only work if the target class does not have final methods, as a dynamic subclass will be created at runtime.
It's possible to cast a proxy obtained from this factory to Advised
,
or to obtain the ProxyFactoryBean reference and programmatically manipulate it.
This won't work for existing prototype references, which are independent. However,
it will work for prototypes subsequently obtained from the factory. Changes to
interception will work immediately on singletons (including existing references).
However, to change interfaces or target it's necessary to obtain a new instance
from the factory. This means that singleton instances obtained from the factory
do not have the same object identity. However, they do have the same interceptors
and target, and changing any reference will change all objects.
setInterceptorNames(java.lang.String...)
,
setProxyInterfaces(java.lang.Class<?>[])
,
MethodInterceptor
,
Advisor
,
Advised
,
Serialized FormModifier and Type | Class and Description |
---|---|
private static class |
ProxyFactoryBean.PrototypePlaceholderAdvisor
Used in the interceptor chain where we need to replace a bean with a prototype
on creating a proxy.
|
Modifier and Type | Field and Description |
---|---|
private AdvisorAdapterRegistry |
advisorAdapterRegistry |
private boolean |
advisorChainInitialized
Whether the advisor chain has already been initialized
|
private boolean |
autodetectInterfaces |
private BeanFactory |
beanFactory |
private boolean |
classLoaderConfigured |
private boolean |
freezeProxy |
static java.lang.String |
GLOBAL_SUFFIX
This suffix in a value in an interceptor list indicates to expand globals.
|
private java.lang.String[] |
interceptorNames |
protected Log |
logger |
private java.lang.ClassLoader |
proxyClassLoader |
private boolean |
singleton |
private java.lang.Object |
singletonInstance
If this is a singleton, the cached singleton proxy instance
|
private java.lang.String |
targetName |
advisorChainFactory, EMPTY_TARGET_SOURCE, targetSource
exposeProxy, opaque
Constructor and Description |
---|
ProxyFactoryBean() |
Modifier and Type | Method and Description |
---|---|
private void |
addAdvisorOnChainCreation(java.lang.Object next,
java.lang.String name)
Invoked when advice chain is created.
|
private void |
addGlobalAdvisor(ListableBeanFactory beanFactory,
java.lang.String prefix)
Add all global interceptors and pointcuts.
|
protected void |
adviceChanged()
Blow away and recache singleton on an advice change.
|
private void |
checkInterceptorNames()
Check the interceptorNames list whether it contains a target name as final element.
|
protected java.lang.Class<?> |
createCompositeInterface(java.lang.Class<?>[] interfaces)
Create a composite interface Class for the given interfaces,
implementing the given interfaces in one single Class.
|
private java.util.List<Advisor> |
freshAdvisorChain()
Return an independent advisor chain.
|
private TargetSource |
freshTargetSource()
Return a TargetSource to use when creating a proxy.
|
java.lang.Object |
getObject()
Return a proxy.
|
java.lang.Class<?> |
getObjectType()
Return the type of the proxy.
|
protected java.lang.Object |
getProxy(AopProxy aopProxy)
Return the proxy object to expose.
|
private java.lang.Object |
getSingletonInstance()
Return the singleton instance of this class's proxy object,
lazily creating it if it hasn't been created already.
|
private void |
initializeAdvisorChain()
Create the advisor (interceptor) chain.
|
private boolean |
isNamedBeanAnAdvisorOrAdvice(java.lang.String beanName)
Look at bean factory metadata to work out whether this bean name,
which concludes the interceptorNames list, is an Advisor or Advice,
or may be a target.
|
boolean |
isSingleton()
Is the object managed by this factory a singleton? That is,
will
FactoryBean.getObject() always return the same object
(a reference that can be cached)? |
private Advisor |
namedBeanToAdvisor(java.lang.Object next)
Convert the following object sourced from calling getBean() on a name in the
interceptorNames array to an Advisor or TargetSource.
|
private java.lang.Object |
newPrototypeInstance()
Create a new prototype instance of this class's created proxy object,
backed by an independent AdvisedSupport configuration.
|
private void |
readObject(java.io.ObjectInputStream ois) |
void |
setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry)
Specify the AdvisorAdapterRegistry to use.
|
void |
setAutodetectInterfaces(boolean autodetectInterfaces)
Set whether to autodetect proxy interfaces if none specified.
|
void |
setBeanClassLoader(java.lang.ClassLoader classLoader)
Callback that supplies the bean
class loader to
a bean instance. |
void |
setBeanFactory(BeanFactory beanFactory)
Callback that supplies the owning factory to a bean instance.
|
void |
setFrozen(boolean frozen)
Set whether this config should be frozen.
|
void |
setInterceptorNames(java.lang.String... interceptorNames)
Set the list of Advice/Advisor bean names.
|
void |
setProxyClassLoader(java.lang.ClassLoader classLoader)
Set the ClassLoader to generate the proxy class in.
|
void |
setProxyInterfaces(java.lang.Class<?>[] proxyInterfaces)
Set the names of the interfaces we're proxying.
|
void |
setSingleton(boolean singleton)
Set the value of the singleton property.
|
void |
setTargetName(java.lang.String targetName)
Set the name of the target bean.
|
addListener, createAopProxy, getAopProxyFactory, isActive, removeListener, setAopProxyFactory
addAdvice, addAdvice, addAdvisor, addAdvisor, addAdvisors, addAdvisors, addInterface, adviceIncluded, copyConfigurationFrom, copyConfigurationFrom, countAdvicesOfType, getAdvisorChainFactory, getAdvisors, getAdvisorsInternal, getConfigurationOnlyCopy, getInterceptorsAndDynamicInterceptionAdvice, getProxiedInterfaces, getTargetClass, getTargetSource, indexOf, indexOf, isInterfaceProxied, isPreFiltered, removeAdvice, removeAdvisor, removeAdvisor, removeInterface, replaceAdvisor, setAdvisorChainFactory, setInterfaces, setPreFiltered, setTarget, setTargetClass, setTargetSource, toProxyConfigString, toString, updateAdvisorArray
copyFrom, isExposeProxy, isFrozen, isOpaque, isOptimize, isProxyTargetClass, setExposeProxy, setOpaque, setOptimize, setProxyTargetClass
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
isExposeProxy, isFrozen, isProxyTargetClass, setExposeProxy
public static final java.lang.String GLOBAL_SUFFIX
protected final Log logger
private java.lang.String[] interceptorNames
private java.lang.String targetName
private boolean autodetectInterfaces
private boolean singleton
private AdvisorAdapterRegistry advisorAdapterRegistry
private boolean freezeProxy
private transient java.lang.ClassLoader proxyClassLoader
private transient boolean classLoaderConfigured
private transient BeanFactory beanFactory
private boolean advisorChainInitialized
private java.lang.Object singletonInstance
public void setProxyInterfaces(java.lang.Class<?>[] proxyInterfaces) throws java.lang.ClassNotFoundException
This is essentially equivalent to the "setInterfaces" method, but mirrors TransactionProxyFactoryBean's "setProxyInterfaces".
java.lang.ClassNotFoundException
AdvisedSupport.setInterfaces(java.lang.Class<?>...)
,
AbstractSingletonProxyFactoryBean.setProxyInterfaces(java.lang.Class<?>[])
public void setInterceptorNames(java.lang.String... interceptorNames)
The referenced beans should be of type Interceptor, Advisor or Advice The last entry in the list can be the name of any bean in the factory. If it's neither an Advice nor an Advisor, a new SingletonTargetSource is added to wrap it. Such a target bean cannot be used if the "target" or "targetSource" or "targetName" property is set, in which case the "interceptorNames" array must contain only Advice/Advisor bean names.
NOTE: Specifying a target bean as final name in the "interceptorNames"
list is deprecated and will be removed in a future Spring version.
Use the "targetName"
property instead.
MethodInterceptor
,
Advisor
,
Advice
,
SingletonTargetSource
public void setTargetName(java.lang.String targetName)
You can also specify a target object or a TargetSource object directly, via the "target"/"targetSource" property, respectively.
public void setAutodetectInterfaces(boolean autodetectInterfaces)
Default is "true". Turn this flag off to create a CGLIB proxy for the full target class if no interfaces specified.
ProxyConfig.setProxyTargetClass(boolean)
public void setSingleton(boolean singleton)
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry)
GlobalAdvisorAdapterRegistry
public void setFrozen(boolean frozen)
ProxyConfig
When a config is frozen, no advice changes can be made. This is useful for optimization, and useful when we don't want callers to be able to manipulate configuration after casting to Advised.
setFrozen
in class ProxyConfig
public void setProxyClassLoader(java.lang.ClassLoader classLoader)
Default is the bean ClassLoader, i.e. the ClassLoader used by the containing BeanFactory for loading all bean classes. This can be overridden here for specific proxies.
public void setBeanClassLoader(java.lang.ClassLoader classLoader)
BeanClassLoaderAware
class 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.
setBeanClassLoader
in interface BeanClassLoaderAware
classLoader
- the owning class loader; may be null
in
which case a default ClassLoader
must be used, for example
the ClassLoader
obtained via
ClassUtils.getDefaultClassLoader()
public void setBeanFactory(BeanFactory beanFactory)
BeanFactoryAware
Invoked after the population of normal bean properties
but before an initialization callback such as
InitializingBean.afterPropertiesSet()
or a custom init-method.
setBeanFactory
in interface BeanFactoryAware
beanFactory
- owning BeanFactory (never null
).
The bean can immediately call methods on the factory.BeanInitializationException
public java.lang.Object getObject() throws BeansException
getObject()
for a proxy.getObject
in interface FactoryBean<java.lang.Object>
BeansException
FactoryBeanNotInitializedException
public java.lang.Class<?> getObjectType()
getObjectType
in interface FactoryBean<java.lang.Object>
null
if not known at the time of the callTargetSource.getTargetClass()
public boolean isSingleton()
FactoryBean
FactoryBean.getObject()
always return the same object
(a reference that can be cached)?
NOTE: If a FactoryBean indicates to hold a singleton object,
the object returned from getObject()
might get cached
by the owning BeanFactory. Hence, do not return true
unless the FactoryBean always exposes the same reference.
The singleton status of the FactoryBean itself will generally be provided by the owning BeanFactory; usually, it has to be defined as singleton there.
NOTE: This method returning false
does not
necessarily indicate that returned objects are independent instances.
An implementation of the extended SmartFactoryBean
interface
may explicitly indicate independent instances through its
SmartFactoryBean.isPrototype()
method. Plain FactoryBean
implementations which do not implement this extended interface are
simply assumed to always return independent instances if the
isSingleton()
implementation returns false
.
The default implementation returns true
, since a
FactoryBean
typically manages a singleton instance.
isSingleton
in interface FactoryBean<java.lang.Object>
FactoryBean.getObject()
,
SmartFactoryBean.isPrototype()
protected java.lang.Class<?> createCompositeInterface(java.lang.Class<?>[] interfaces)
The default implementation builds a JDK proxy class for the given interfaces.
interfaces
- the interfaces to mergeProxy.getProxyClass(java.lang.ClassLoader, java.lang.Class<?>...)
private java.lang.Object getSingletonInstance()
private java.lang.Object newPrototypeInstance()
protected java.lang.Object getProxy(AopProxy aopProxy)
The default implementation uses a getProxy
call with
the factory's bean class loader. Can be overridden to specify a
custom class loader.
aopProxy
- the prepared AopProxy instance to get the proxy fromAopProxy.getProxy(ClassLoader)
private void checkInterceptorNames()
private boolean isNamedBeanAnAdvisorOrAdvice(java.lang.String beanName)
beanName
- bean name to checktrue
if it's an Advisor or Adviceprivate void initializeAdvisorChain() throws AopConfigException, BeansException
AopConfigException
BeansException
private java.util.List<Advisor> freshAdvisorChain()
private void addGlobalAdvisor(ListableBeanFactory beanFactory, java.lang.String prefix)
private void addAdvisorOnChainCreation(java.lang.Object next, java.lang.String name)
Add the given advice, advisor or object to the interceptor list. Because of these three possibilities, we can't type the signature more strongly.
next
- advice, advisor or target objectname
- bean name from which we obtained this object in our owning
bean factoryprivate TargetSource freshTargetSource()
private Advisor namedBeanToAdvisor(java.lang.Object next)
protected void adviceChanged()
adviceChanged
in class ProxyCreatorSupport
AdvisedSupportListener.adviceChanged(org.springframework.aop.framework.AdvisedSupport)
private void readObject(java.io.ObjectInputStream ois) throws java.io.IOException, java.lang.ClassNotFoundException
java.io.IOException
java.lang.ClassNotFoundException