天天看點

AOP 工廠對象之ScopedProxyFactoryBean 原了解析

J2EE開發者,對購物車這個概念太熟悉了。存在于Session周期中。今天就說說,如果用Spring管理購物車,怎麼處理。

使用場景

1

2

3

<code>&lt;</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>&gt;</code>

<code>    </code><code>&lt;</code><code>aop:scoped-proxy</code>  <code>proxy-target-class</code><code>=</code><code>"true"</code><code>/&gt;</code>

<code>&lt;/</code><code>bean</code><code>&gt;</code>

必須要聲明 &lt;aop:scoped-proxy..&gt;

或者 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,如需轉載請自行聯系原作者