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;
}
}
...
}
转载于:https://blog.51cto.com/dba10g/1929157