|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.apache.myfaces.orchestra.conversation.spring.AbstractSpringOrchestraScope
public abstract class AbstractSpringOrchestraScope
Abstract basis class for all the Orchestra scopes.
A scope object has two quite different roles:
This base class handles item 1 above, and leaves item 2 to a subclass. The declaration of interface ConversationFactory needs to be on this class, however, as the createBean method needs to invoke it.
Constructor Summary | |
---|---|
AbstractSpringOrchestraScope()
|
Method Summary | |
---|---|
protected void |
assertSameScope(String beanName,
Conversation conversation)
Verify that the specified conversation was created by this scope object. |
protected String |
buildBeanName(String name)
Deprecated. Should not be necessary in user code. |
void |
defineBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory cbf)
Register any BeanPostProcessors that are needed by this scope. |
Object |
get(String name,
org.springframework.beans.factory.ObjectFactory objectFactory)
This is invoked by Spring whenever someone calls getBean(name) on a bean-factory and the bean-definition for that bean has a scope attribute that maps to an instance of this class. |
protected org.aopalliance.aop.Advice[] |
getAdvices()
|
protected org.springframework.context.ConfigurableApplicationContext |
getApplicationContext()
|
protected Conversation |
getConversationForBean(String beanDefName)
Get the conversation for the given beanName. |
String |
getConversationId()
Return the conversation context id. |
String |
getConversationNameForBean(String beanName)
Get the conversation-name for bean instances created using the specified bean definition. |
protected String |
getExplicitConversationName(org.springframework.beans.factory.config.BeanDefinition beanDef)
Return the explicit conversation name for this bean definition, or null if there is none. |
protected Object |
getProxy(String beanName,
org.springframework.beans.factory.ObjectFactory objectFactory)
Return a CGLIB-generated proxy class for the beanclass that is specified by the provided beanName. |
protected Object |
getRealBean(String conversationName,
String beanName,
org.springframework.beans.factory.ObjectFactory objectFactory)
Get a real bean instance (not a scoped-proxy). |
protected void |
notifyAccessConversation(Conversation conversation)
|
void |
registerDestructionCallback(String name,
Runnable runnable)
Add the given runnable wrapped within an ConversationBindingListener to
the conversation map. |
Object |
remove(String name)
|
void |
setAdvices(org.aopalliance.aop.Advice[] advices)
The advices (interceptors) which will be applied to the conversation scoped bean. |
void |
setApplicationContext(org.springframework.context.ApplicationContext applicationContext)
Get an ApplicationContext injected by Spring. |
void |
setAutoProxy(boolean state)
Configuration for a scope object to control whether "scoped proxy" objects are automatically wrapped around each conversation bean. |
void |
setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)
Invoked by Spring to notify this object of the BeanFactory it is associated with. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Methods inherited from interface org.apache.myfaces.orchestra.conversation.ConversationFactory |
---|
createConversation |
Constructor Detail |
---|
public AbstractSpringOrchestraScope()
Method Detail |
---|
public void setAdvices(org.aopalliance.aop.Advice[] advices)
An application's spring configuration uses this method to control what advices are applied to beans generated from this scope. One commonly applied advice is the Orchestra persistence interceptor, which ensures that whenever a method on a conversation-scoped bean is invoked the "global persistence context" is set to the context for the conversation that bean is in.
Note [1]: the advices are only applied when the bean is invoked via its proxy. If invoked via the "this" pointer of the object the interceptors will not run. This is generally a good thing, as they are not wanted when a method on the bean invokes another method on the same bean. However it is bad if the bean passes "this" as a parameter to some other object that makes a callback on it at some later time. In that case, the bean must take care to pass its proxy to the remote object, not itself. See method ConversationUtils.getCurrentBean().
protected org.aopalliance.aop.Advice[] getAdvices()
public void setAutoProxy(boolean state)
Automatically applying scope proxies solves a lot of tricky problems with "stale" beans, and should generally be used. However it does require CGLIB to be present in the classpath. It also can impact performance in some cases. Where this is a problem, this flag can turn autoproxying off. Note that the standard spring aop:scoped-proxy bean can then be used on individual beans to re-enable proxying for specific beans if desired.
This defaults to true.
public String getConversationId()
Note: This conversationId is something spring requires. It has nothing to do with the Orchestra conversation id.
TODO: what does Spring use this for????
getConversationId
in interface org.springframework.beans.factory.config.Scope
public Object get(String name, org.springframework.beans.factory.ObjectFactory objectFactory)
In the normal case, this method returns an internally-created proxy object that fetches the "real" bean every time a method is invoked on the proxy (see method getRealBean). This does obviously have some performance impact. However it is necessary when beans from one conversation are referencing beans from another conversation as the conversation lifetimes are not the same; without this proxying there are many cases where "stale" references end up being used. Most references to conversation-scoped objects are made via EL expressions, and in this case the performance impact is not significant relative to the overhead of EL. Note that there is one case where this proxying is not "transparent" to user code: if a proxied object passes a "this" pointer to a longer-lived object that retains that pointer then that reference can be "stale", as it points directly to an instance rather than to the proxy.
When the Spring aop:scoped-proxy feature is applied to conversation-scoped beans, then this functionality is disabled as aop:scoped-proxy has a very similar effect. Therefore, when this method detects that it has been invoked by a proxy object generated by aop:scoped-proxy then it returns the real object (see getRealBean) rather than another proxy. Using aop:scoped-proxy is somewhat less efficient than Orchestra's customised proxying.
And when the orchestra proxy needs to access the real object, it won't call this method; instead, getRealBean is called directly. See class ScopedBeanTargetSource.
get
in interface org.springframework.beans.factory.config.Scope
protected Object getProxy(String beanName, org.springframework.beans.factory.ObjectFactory objectFactory)
When any method is invoked on this proxy, it invokes method getRealBean on this same instance in order to locate a proper instance, then forwards the method call to it.
There is a separate proxy instance per beandef (shared across all instances of that bean). This instance is created when first needed, and cached for reuse.
protected Object getRealBean(String conversationName, String beanName, org.springframework.beans.factory.ObjectFactory objectFactory)
The appropriate Conversation is retrieved; if it does not yet exist then it is created and started. The conversation name is either specified on the bean-definition via a custom attribute, or defaults to the bean name.
Then if the bean already exists in the Conversation it is returned. Otherwise a new instance is created, stored into the Conversation and returned.
When a bean is created, a proxy is actually created for it which has one or more AOP "advices" (ie method interceptors). The CurrentConversationAdvice class is always attached. Note that if the bean definition contains the aop:proxy tag (and most do) then the bean that spring creates is already a proxy, ie what is returned is a proxy of a proxy.
conversationName
- beanName
- is the key within the conversation of the bean we are interested in.protected void assertSameScope(String beanName, Conversation conversation)
beanName
- is just used when generating an error message on failure.conversation
- is the conversation to validate.protected void notifyAccessConversation(Conversation conversation)
public void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory) throws org.springframework.beans.BeansException
This method is redundant as we also have setApplicationContext. However as this method (and the BeanFactoryAware interface on this class) were present in release 1.0 this needs to be kept for backwards compatibility.
setBeanFactory
in interface org.springframework.beans.factory.BeanFactoryAware
org.springframework.beans.BeansException
public void defineBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory cbf) throws org.springframework.beans.BeansException
This is an alternative to requiring users to also add an orchestra BeanPostProcessor element to their xml configuration file manually.
When a bean instance is created by Spring, it always runs every single BeanPostProcessor that has been registered with it.
org.springframework.beans.BeansException
protected Conversation getConversationForBean(String beanDefName)
public String getConversationNameForBean(String beanName)
protected String getExplicitConversationName(org.springframework.beans.factory.config.BeanDefinition beanDef)
This is a separate method so that subclasses can determine conversation names via alternate methods. In particular, a subclass may want to look for an annotation on the class specified by the definition.
protected String buildBeanName(String name)
This method will simply strip off anything before the first dot.
public Object remove(String name)
remove
in interface org.springframework.beans.factory.config.Scope
public void registerDestructionCallback(String name, Runnable runnable)
ConversationBindingListener
to
the conversation map.
This ensures it will be called during conversation destroy.
Spring calls this method whenever a bean in this scope is created, if that bean has a "destroy method". Note however that it appears that it can also call it even for beans that do not have a destroy method when there is a "destruction aware" BeanPostProcessor attached to the context (spring version 2.5 at least).
When an aop:scoped-proxy has been used inside the bean, then the "new" definition does not have any scope attribute, so orchestra is not invoked for it. However the "renamed" bean does, and so this is called.
registerDestructionCallback
in interface org.springframework.beans.factory.config.Scope
public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws org.springframework.beans.BeansException
setApplicationContext
in interface org.springframework.context.ApplicationContextAware
org.springframework.beans.BeansException
protected org.springframework.context.ConfigurableApplicationContext getApplicationContext()
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |