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