J2EE开发者,对购物车这个概念太熟悉了。存在于Session周期中。今天就说说,如果用Spring管理购物车,怎么处理。
使用场景
1
2
3
<code><</code><code>bean</code> <code>id</code><code>=</code><code>"cart"</code> <code>class</code><code>=</code><code>"com.hellojd.jpetstore.domain.model.Cart"</code> <code>scope</code><code>=</code><code>"session"</code><code>></code>
<code> </code><code><</code><code>aop:scoped-proxy</code> <code>proxy-target-class</code><code>=</code><code>"true"</code><code>/></code>
<code></</code><code>bean</code><code>></code>
必须要声明 <aop:scoped-proxy..>
或者 annotation配置
4
5
<code>@Scope</code><code>(value=</code><code>"session"</code><code>,proxyMode= ScopedProxyMode.TARGET_CLASS)</code>
<code>@Component</code>
<code>public</code> <code>class</code> <code>Cart </code><code>implements</code> <code>Serializable {</code>
<code>...</code>
<code>}</code>
经过上面的配置,就可以在controller中,注入使用了。
接下来,分析spring是如何管理购物车的.
2. 源码分析
2.1 ScopedProxyFactoryBean 类图
<a href="https://s2.51cto.com/wyfs02/M00/96/D0/wKiom1kll8HA0NngAABh4fY4Bco101.png-wh_500x0-wm_3-wmp_4-s_3511243032.png" target="_blank"></a>
既然ScopedProxyFactoryBean,是个FactoryBean,就关注下getObject()
6
<code>public</code> <code>Object getObject() {</code>
<code> </code><code>if</code> <code>(</code><code>this</code><code>.proxy == </code><code>null</code><code>) {</code>
<code> </code><code>throw</code> <code>new</code> <code>FactoryBeanNotInitializedException();</code>
<code> </code><code>}</code>
<code> </code><code>return</code> <code>this</code><code>.proxy;</code>
重点是proxy属性的维护了。在BeanFactoryAware.setBeanFactory接口方法中初始化。
发生时机:普通属性注入之后,InitializingBean.afterPropertiesSet() 和 custom init-method之前
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<code>public</code> <code>void</code> <code>setBeanFactory(BeanFactory beanFactory) {</code>
<code> </code><code>if</code> <code>(!(beanFactory </code><code>instanceof</code> <code>ConfigurableBeanFactory)) {</code>
<code> </code><code>throw</code> <code>new</code> <code>IllegalStateException(</code><code>"Not running in a ConfigurableBeanFactory: "</code> <code>+ beanFactory);</code>
<code> </code><code>ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;</code>
<code> </code><code>this</code><code>.scopedTargetSource.setBeanFactory(beanFactory);</code>
<code> </code><code>ProxyFactory pf = </code><code>new</code> <code>ProxyFactory();</code>
<code> </code><code>pf.copyFrom(</code><code>this</code><code>);</code>
<code> </code><code>pf.setTargetSource(</code><code>this</code><code>.scopedTargetSource);</code>
<code> </code><code>Class beanType = beanFactory.getType(</code><code>this</code><code>.targetBeanName);</code>
<code> </code><code>if</code> <code>(beanType == </code><code>null</code><code>) {</code>
<code> </code><code>throw</code> <code>new</code> <code>IllegalStateException(</code><code>"Cannot create scoped proxy for bean '"</code> <code>+ </code><code>this</code><code>.targetBeanName +</code>
<code> </code><code>"': Target type could not be determined at the time of proxy creation."</code><code>);</code>
<code> </code><code>if</code> <code>(!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {</code>
<code> </code><code>//设置源接口</code>
<code> </code><code>pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));</code>
<code> </code><code>// 为增加DefaultScopedObject能力,增加introduction </code>
<code> </code><code>ScopedObject scopedObject = </code><code>new</code> <code>DefaultScopedObject(cbf, </code><code>this</code><code>.scopedTargetSource.getTargetBeanName());</code>
<code> </code><code>pf.addAdvice(</code><code>new</code> <code>DelegatingIntroductionInterceptor(scopedObject));</code>
<code> </code><code>// Add the AopInfrastructureBean marker to indicate that the scoped proxy</code>
<code> </code><code>// itself is not subject to auto-proxying! Only its target bean is.</code>
<code> </code><code>pf.addInterface(AopInfrastructureBean.</code><code>class</code><code>);</code>
<code> </code><code>this</code><code>.proxy = pf.getProxy(cbf.getBeanClassLoader());</code>
<a href="https://s2.51cto.com/wyfs02/M02/96/D0/wKiom1klmWShMzUnAACIPLreQUs791.png" target="_blank"></a>
TargetSource
用于获取AOP调用的当前“目标”
Target
AbstractBeanFactoryBasedTargetSource
基于Spring BeanFactory的实现TargetSource的基类
ProxyConfig
方便的用于创建代理的超类配置
AOP
ProxyFactory
编程式AOP代理工厂
ProxyCreatorSupport
代理工厂的基类
AdvisedSupport
代理配置元信息管理基类AOP
AopProxyFactory
创建AOP代理的工厂
ScopedObject
用于范围对象的AOP接口
完成从spring中获取
DelegatingIntroductionInterceptor
委托引入拦截器
3.RequestScope VS SessionScope
<code>public</code> <code>class</code> <code>SessionScope </code><code>extends</code> <code>AbstractRequestAttributesScope {</code>
<code> </code><code>public</code> <code>String getConversationId() {</code>
<code> </code><code>return</code> <code>RequestContextHolder.currentRequestAttributes().getSessionId();</code>
<code> </code><code>}</code>
<code> </code><code>@Override</code>
<code> </code><code>public</code> <code>Object get(String name, ObjectFactory objectFactory) {</code>
<code> </code><code>Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();</code>
<code> </code><code>synchronized</code> <code>(mutex) {</code>
<code> </code><code>return</code> <code>super</code><code>.get(name, objectFactory);</code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>Object remove(String name) {</code>
<code> </code><code>return</code> <code>super</code><code>.remove(name);</code>
<code> </code><code>...</code>
<code>} </code>
or
<code>public</code> <code>abstract</code> <code>class</code> <code>AbstractRequestAttributesScope </code><code>implements</code> <code>Scope {</code>
<code> </code><code>public</code> <code>Object get(String name, ObjectFactory objectFactory) {</code>
<code> </code><code>RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();</code>
<code> </code><code>Object scopedObject = attributes.getAttribute(name, getScope());</code>
<code> </code><code>if</code> <code>(scopedObject == </code><code>null</code><code>) {</code>
<code> </code><code>scopedObject = objectFactory.getObject();</code>
<code> </code><code>attributes.setAttribute(name, scopedObject, getScope());</code>
<code> </code><code>}</code>
<code> </code><code>return</code> <code>scopedObject;</code>
<code> </code><code>public</code> <code>Object remove(String name) {</code>
<code> </code><code>if</code> <code>(scopedObject != </code><code>null</code><code>) {</code>
<code> </code><code>attributes.removeAttribute(name, getScope());</code>
<code> </code><code>return</code> <code>scopedObject;</code>
<code> </code><code>else</code> <code>{</code>
<code> </code><code>return</code> <code>null</code><code>;</code>
<code> </code><code>...</code>
<code> </code><code>}</code>
<code></code>
本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1929157,如需转载请自行联系原作者