org.springframework.aop.framework
Class ProxyFactoryBean

java.lang.Object
  extended by org.springframework.aop.framework.ProxyConfig
      extended by org.springframework.aop.framework.AdvisedSupport
          extended by org.springframework.aop.framework.ProxyCreatorSupport
              extended by org.springframework.aop.framework.ProxyFactoryBean
All Implemented Interfaces:
java.io.Serializable, Advised, TargetClassAware, Aware, BeanClassLoaderAware, BeanFactoryAware, FactoryBean<java.lang.Object>

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.

Author:
Rod Johnson, Juergen Hoeller
See Also:
setInterceptorNames(java.lang.String[]), setProxyInterfaces(java.lang.Class[]), org.aopalliance.intercept.MethodInterceptor, Advisor, Advised, Serialized Form

Nested Class Summary
private static class ProxyFactoryBean.PrototypePlaceholderAdvisor
          Used in the interceptor chain where we need to replace a bean with a prototype on creating a proxy.
 
Field Summary
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
           
 
Fields inherited from class org.springframework.aop.framework.AdvisedSupport
advisorChainFactory, EMPTY_TARGET_SOURCE, targetSource
 
Fields inherited from class org.springframework.aop.framework.ProxyConfig
exposeProxy, opaque
 
Constructor Summary
ProxyFactoryBean()
           
 
Method Summary
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.
 
Methods inherited from class org.springframework.aop.framework.ProxyCreatorSupport
addListener, createAopProxy, getAopProxyFactory, isActive, removeListener, setAopProxyFactory
 
Methods inherited from class org.springframework.aop.framework.AdvisedSupport
addAdvice, addAdvice, addAdvisor, addAdvisor, addAdvisors, addAdvisors, addAllAdvisors, 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
 
Methods inherited from class org.springframework.aop.framework.ProxyConfig
copyFrom, isExposeProxy, isFrozen, isOpaque, isOptimize, isProxyTargetClass, setExposeProxy, setOpaque, setOptimize, setProxyTargetClass
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface org.springframework.aop.framework.Advised
isExposeProxy, isFrozen, isProxyTargetClass, setExposeProxy
 

Field Detail

GLOBAL_SUFFIX

public static final java.lang.String GLOBAL_SUFFIX
This suffix in a value in an interceptor list indicates to expand globals.

See Also:
Constant Field Values

logger

protected final Log logger

interceptorNames

private java.lang.String[] interceptorNames

targetName

private java.lang.String targetName

autodetectInterfaces

private boolean autodetectInterfaces

singleton

private boolean singleton

advisorAdapterRegistry

private AdvisorAdapterRegistry advisorAdapterRegistry

freezeProxy

private boolean freezeProxy

proxyClassLoader

private transient java.lang.ClassLoader proxyClassLoader

classLoaderConfigured

private transient boolean classLoaderConfigured

beanFactory

private transient BeanFactory beanFactory

advisorChainInitialized

private boolean advisorChainInitialized
Whether the advisor chain has already been initialized


singletonInstance

private java.lang.Object singletonInstance
If this is a singleton, the cached singleton proxy instance

Constructor Detail

ProxyFactoryBean

public ProxyFactoryBean()
Method Detail

setProxyInterfaces

public void setProxyInterfaces(java.lang.Class[] proxyInterfaces)
                        throws java.lang.ClassNotFoundException
Set the names of the interfaces we're proxying. If no interface is given, a CGLIB for the actual class will be created.

This is essentially equivalent to the "setInterfaces" method, but mirrors TransactionProxyFactoryBean's "setProxyInterfaces".

Throws:
java.lang.ClassNotFoundException
See Also:
AdvisedSupport.setInterfaces(java.lang.Class[]), AbstractSingletonProxyFactoryBean.setProxyInterfaces(java.lang.Class[])

setInterceptorNames

public void setInterceptorNames(java.lang.String[] interceptorNames)
Set the list of Advice/Advisor bean names. This must always be set to use this factory bean in a bean factory.

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.

See Also:
org.aopalliance.intercept.MethodInterceptor, Advisor, org.aopalliance.aop.Advice, SingletonTargetSource

setTargetName

public void setTargetName(java.lang.String targetName)
Set the name of the target bean. This is an alternative to specifying the target name at the end of the "interceptorNames" array.

You can also specify a target object or a TargetSource object directly, via the "target"/"targetSource" property, respectively.

See Also:
setInterceptorNames(String[]), AdvisedSupport.setTarget(Object), AdvisedSupport.setTargetSource(org.springframework.aop.TargetSource)

setAutodetectInterfaces

public void setAutodetectInterfaces(boolean autodetectInterfaces)
Set whether to autodetect proxy interfaces if none specified.

Default is "true". Turn this flag off to create a CGLIB proxy for the full target class if no interfaces specified.

See Also:
ProxyConfig.setProxyTargetClass(boolean)

setSingleton

public void setSingleton(boolean singleton)
Set the value of the singleton property. Governs whether this factory should always return the same proxy instance (which implies the same target) or whether it should return a new prototype instance, which implies that the target and interceptors may be new instances also, if they are obtained from prototype bean definitions. This allows for fine control of independence/uniqueness in the object graph.


setAdvisorAdapterRegistry

public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry)
Specify the AdvisorAdapterRegistry to use. Default is the global AdvisorAdapterRegistry.

See Also:
GlobalAdvisorAdapterRegistry

setFrozen

public void setFrozen(boolean frozen)
Description copied from class: ProxyConfig
Set whether this config should be frozen.

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.

Overrides:
setFrozen in class ProxyConfig

setProxyClassLoader

public void setProxyClassLoader(java.lang.ClassLoader classLoader)
Set the ClassLoader to generate the proxy class in.

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.


setBeanClassLoader

public void setBeanClassLoader(java.lang.ClassLoader classLoader)
Description copied from interface: BeanClassLoaderAware
Callback that supplies the bean 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.

Specified by:
setBeanClassLoader in interface BeanClassLoaderAware
Parameters:
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()

setBeanFactory

public void setBeanFactory(BeanFactory beanFactory)
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 interface BeanFactoryAware
Parameters:
beanFactory - owning BeanFactory (never null). The bean can immediately call methods on the factory.
See Also:
BeanInitializationException

getObject

public java.lang.Object getObject()
                           throws BeansException
Return a proxy. Invoked when clients obtain beans from this factory bean. Create an instance of the AOP proxy to be returned by this factory. The instance will be cached for a singleton, and create on each call to getObject() for a proxy.

Specified by:
getObject in interface FactoryBean<java.lang.Object>
Returns:
a fresh AOP proxy reflecting the current state of this factory
Throws:
BeansException
See Also:
FactoryBeanNotInitializedException

getObjectType

public java.lang.Class<?> getObjectType()
Return the type of the proxy. Will check the singleton instance if already created, else fall back to the proxy interface (in case of just a single one), the target bean type, or the TargetSource's target class.

Specified by:
getObjectType in interface FactoryBean<java.lang.Object>
Returns:
the type of object that this FactoryBean creates, or null if not known at the time of the call
See Also:
TargetSource.getTargetClass()

isSingleton

public boolean isSingleton()
Description copied from interface: FactoryBean
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)?

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.

Specified by:
isSingleton in interface FactoryBean<java.lang.Object>
Returns:
whether the exposed object is a singleton
See Also:
FactoryBean.getObject(), SmartFactoryBean.isPrototype()

createCompositeInterface

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.

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:
Proxy.getProxyClass(java.lang.ClassLoader, java.lang.Class...)

getSingletonInstance

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.

Returns:
the shared singleton proxy

newPrototypeInstance

private java.lang.Object newPrototypeInstance()
Create a new prototype instance of this class's created proxy object, backed by an independent AdvisedSupport configuration.

Returns:
a totally independent proxy, whose advice we may manipulate in isolation

getProxy

protected java.lang.Object getProxy(AopProxy aopProxy)
Return the proxy object to expose.

The default implementation uses a getProxy call with the factory's bean class loader. Can be overridden to specify a custom class loader.

Parameters:
aopProxy - the prepared AopProxy instance to get the proxy from
Returns:
the proxy object to expose
See Also:
AopProxy.getProxy(ClassLoader)

checkInterceptorNames

private void checkInterceptorNames()
Check the interceptorNames list whether it contains a target name as final element. If found, remove the final name from the list and set it as targetName.


isNamedBeanAnAdvisorOrAdvice

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.

Parameters:
beanName - bean name to check
Returns:
true if it's an Advisor or Advice

initializeAdvisorChain

private void initializeAdvisorChain()
                             throws AopConfigException,
                                    BeansException
Create the advisor (interceptor) chain. Aadvisors that are sourced from a BeanFactory will be refreshed each time a new prototype instance is added. Interceptors added programmatically through the factory API are unaffected by such changes.

Throws:
AopConfigException
BeansException

freshAdvisorChain

private java.util.List<Advisor> freshAdvisorChain()
Return an independent advisor chain. We need to do this every time a new prototype instance is returned, to return distinct instances of prototype Advisors and Advices.


addGlobalAdvisor

private void addGlobalAdvisor(ListableBeanFactory beanFactory,
                              java.lang.String prefix)
Add all global interceptors and pointcuts.


addAdvisorOnChainCreation

private void addAdvisorOnChainCreation(java.lang.Object next,
                                       java.lang.String name)
Invoked when advice chain is created.

Add the given advice, advisor or object to the interceptor list. Because of these three possibilities, we can't type the signature more strongly.

Parameters:
next - advice, advisor or target object
name - bean name from which we obtained this object in our owning bean factory

freshTargetSource

private TargetSource freshTargetSource()
Return a TargetSource to use when creating a proxy. If the target was not specified at the end of the interceptorNames list, the TargetSource will be this class's TargetSource member. Otherwise, we get the target bean and wrap it in a TargetSource if necessary.


namedBeanToAdvisor

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.


adviceChanged

protected void adviceChanged()
Blow away and recache singleton on an advice change.

Overrides:
adviceChanged in class ProxyCreatorSupport
See Also:
AdvisedSupportListener.adviceChanged(org.springframework.aop.framework.AdvisedSupport)

readObject

private void readObject(java.io.ObjectInputStream ois)
                 throws java.io.IOException,
                        java.lang.ClassNotFoundException
Throws:
java.io.IOException
java.lang.ClassNotFoundException